>  기사  >  웹 프론트엔드  >  프런트엔드 작성 test-JS 암시적 변환 문제의 함정

프런트엔드 작성 test-JS 암시적 변환 문제의 함정

hzc
hzc앞으로
2020-06-17 10:00:321903검색

필기 시험 문제를 작성할 때

"1" + 2
obj + 1
[] == ![] 
[null] == false

=== 및 ==

=== 叫做严格运算符,对象类型指向地址相同或原始类型( 数值、字符串、布尔值)值相同;==叫做相等运算符,类型不同会进行转化再比较,undefined、null相等,对象类型还是比较引用。==运算符将原始值和其包装对象视为相等,但=== 연산자와 같이 암시적 변환이 포함된 문제를 자주 접하게 됩니다. 모두 obj.a==null(obj.a=== null || obj.a ===정의되지 않음과 동일). obj.a=== null || obj.a ===undefined)。

相等运算符就是常常引起JS隐式转换的坑货,它也常常出现在我们的面试题中,不过我们在现实开发中,为了避免不必要的问题要求使用严格运算符,但是了解还是很有必要的。

想要了解JS隐式转换,就要先从三个知识点下手。

原始类型

原始类型(基本类型、基本数据类型、原始数据类型)是一种既非对象也无方法的数据。在 JavaScript 中,共有7种:string,number,bigint,boolean,null,undefined,symbol (ECMAScript 2016新增)

falsy 值 (虚值)

falsy 值 (虚值) 是在 Boolean 上下文中认定为 false 的值,在JavaScript只有 七个 falsy 值。

  1. false false 关键字
  2. 0 数值 zero
  3. 0n 当 BigInt 作为布尔值使用时, 遵从其作为数值的规则. 0n 是 falsy 值.
  4. 一个空字符串 (字符串的长度为零). JavaScript 中的字符串可用双引号 "", 单引号 '', 或 模板字面量 `` 定义。
  5. null null - 缺少值
  6. undefined undefined - 原始值
  7. NaN NaN - 非数值

特别要说明的是,除了这七个对象全是真值,如new Number 和new Boolean 都是真值。

let b = new Boolean(false);i
f(b){
//会执行到这里。
}

四大转换规则

  • toString规则:其他类型的值转换为字符串类型的操作

    • null => "null"
    • undefined => "undefined"
    • true => "true"  false=>"false"
    • 10 => "10"  "1e21"=>"1e+21"
    • [1,2,3] => "1,2,3"
    • Object对象 => "[Object Object]"  其实是调用toString方法
  • ToPrimitive规则:对象类型数组转为原始类型的操作

    • 当对象类型需要被转为原始类型时,它会先查找对象的valueOf方法,如果valueOf方法返回原始类型的值,则ToPrimitive的结果就是这个值
    • 如果valueOf不存在或者valueOf方法返回的不是原始类型的值,就会尝试调用对象的toString方法,也就是会遵循对象的ToString规则,然后使用toString的返回值作为ToPrimitive的结果
    • Date 是先toString再ValueOf
    • 如果在toString再ValueOf后都不能拿到原始类型,再判断相等、加减时就抛出Uncaught TypeError: Cannot convert object to primitive value
    • 항등 연산자는 JS에서 종종 암시적 변환을 일으키는 사기입니다. 하지만 실제 개발에서는 불필요한 문제를 피하기 위해 엄격한 연산자를 사용해야 하지만 여전히 그렇습니다. 매우 이해하기 쉽습니다.
  • JS 암시적 변환을 이해하려면 먼저 세 가지 지식 포인트부터 시작해야 합니다.
  • 기본 유형

    기본 유형(기본 유형, 기본 데이터 유형, 원시 데이터 유형)은 객체도 메소드도 아닌 데이터입니다. JavaScript에는 7가지 유형이 있습니다: string, number, bigint, boolean, null, 정의되지 않음, 기호(ECMAScript 2016의 새로운 기능).

    falsy 값(가상 값)
      falsy 값(가상 값)은 Boolean 문맥에서 false로 인식되는 값으로,
    • seven
    • 만 있습니다. JavaScript 거짓 값.
      1. false false 키워드
      2. 0 값 0
      3. 0n BigInt를 부울 값으로 사용하는 경우 숫자 값으로 사용되는 규칙을 따릅니다. 0n은 거짓 값입니다.
      4. 빈 문자열( string은 0입니다.) JavaScript의 문자열은 큰따옴표 "", 작은따옴표 '' 또는 템플릿 리터럴 ``로 정의할 수 있습니다.

    • null null - 누락된 값
    • undefin힌정되지 않음 - 원래 값 NaN NaN - 숫자가 아닌 값

        특히, 이 7개 객체를 제외하면 new Number, new 등 모두 참값입니다. 부울은 참값입니다.
      • [] == [] 
        [] == ![] 
        [null] == false

        4가지 주요 변환 규칙

    toString 규칙

    : 다른 유형의 값을 문자열 유형으로 변환하는 작업

    🎜null => ; "null"🎜🎜undefine => "정의되지 않음"🎜🎜true => "true" false=>"false"🎜🎜10 => "10" "1e21"=>"1e+21"🎜 🎜 [1,2,3] => "1,2,3"🎜🎜Object 객체 => "[Object Object]"는 실제로 toString 메서드🎜🎜🎜🎜🎜🎜ToPrimitive 규칙🎜을 호출합니다. Primitive 유형으로 변환됩니다🎜🎜🎜객체 유형을 원시 유형으로 변환해야 하는 경우 먼저 객체의 valueOf 메서드를 조회합니다. valueOf 메서드가 원래 유형의 값을 반환하면 ToPrimitive의 결과입니다. 이 값인가요🎜🎜valueOf가 존재하지 않거나 valueOf 메서드가 기본 유형이 아닌 값을 반환하는 경우 개체의 toString 메서드를 호출하려고 시도합니다. 이는 개체의 ToString 규칙을 따른 다음 반환을 사용한다는 의미입니다. ToPrimitive🎜🎜Date의 결과로 toString의 값은 먼저 toString이고 그 다음 ValueOf🎜🎜toString이 ValueOf 이후에 원래 유형을 얻을 수 없고, 동등, 덧셈 또는 뺄셈을 판단할 때 Uncaught TypeError: Cannot Convert object를 발생시킵니다. 기본 값으로🎜🎜🎜🎜🎜🎜ToNumber 규칙🎜🎜🎜🎜null => 0🎜🎜undefine => NaN🎜🎜"123"=>123 "12ssd"=>NaN ""= >0🎜🎜false => 0 true=>1🎜🎜array, object ToPrimitive🎜🎜🎜🎜🎜🎜ToBoolean rule🎜🎜🎜🎜js의 7가지 거짓 값(가상 값)은 false이고 다른 것들은 사실입니다🎜🎜🎜🎜🎜암시적 변환🎜🎜위의 지식 포인트를 이해하면 JS 암시적 변환을 단번에 무너뜨릴 수 있습니다. 🎜
    • == 的过程(优先换成数字、字符串)
    1. 首先看==前后有没有NaN,有的话都是返回false。NaN不等于任何值,包括其本身
    2. 布尔值会转成数字类型,true转成1,false转成0
    3. 数字和字符串比较,字符串会转成数字
    4. undefined和null除了和undefined或null相等,和其他相比都是false
    5. 数字或者字符串和对象相比,对象使用ToPrimitive规则转换。
    6. 当两个操作数都是对象时,JavaScript会比较其内部引用,当且仅当他们的引用指向内存中的相同对象(区域)时才相等,即他们在栈内存中的引用地址相同。
    • +的过程(优先换成字符串、数字)
    1. 如果至少有一个操作数是对象,它会被转换成原始值(字符串,数字或布尔);
    2. 转换之后,如果至少有一个操作数是字符串类型,第二个操作数会被转换成字符串,并且会执行连接。
    3. 在其他的情况下,两个操作数都会转换成数字并执行算数加法运算。
    • -的过程(转换成数字) 这个就很简单了,全部用ToNumber规则转换成数字

    检测学习成果

    我们根据以上所学看几个笔试题。如果你都知道结果,就不用看我的废解释了。

    [] == [] 
    [] == ![] 
    [null] == false

    第一个,==左右都是对象,比较引用地址,这个两个不同的实例,肯定不相等啊。 第二个,!的优先级高于==,所以先 [] 是真值,求非当让是false了,转成数字0,==左是对象右是数字,对象使用ToPrimitive规则转换成"",再用ToNumber规则就转成0了,判断为相等。 第三个,[null]ToPrimitive再ToNumber规则就转成0,false也转成0。

    var  a = 1;
    var  b = "3";
    
    var obj1 = {
        i:1,
        toString:function() {
            return "1";
        },
        valueOf:function() {
            return 1;
        }
    };
    var obj2 = {
        i:1,
        toString:function() {
            return "2";
        }
    };
    var obj3 = {
        i:1,
        valueOf:function() {
            return 3;
        }
    };
    var obj = {
        i:1,
    };
    var objE = {
        i:1,
        valueOf:function() {
            return [];
        },
        toString:function() {
            return {};
        }
    };
    
    
    a+b  
    a + obj  
    a + objE 
    
    a+obj1  
    a+obj2  
    a+obj3  
    
    b+obj1  
    b+obj2  
    b+obj3  
    
    a==obj2  
    a==obj1

    这道题比较简单你只要熟练掌握我上面说的那几个知识点可以了。下面直接写出结果啦。

    a + b    //"13"
    a + obj  //"1[object Object]"
    a + objE //Uncaught TypeError: Cannot convert object to primitive value
    
    a+obj1  //2
    a+obj2  //"12"
    a+obj3  // 4
    
    b+obj1  //"31"
    b+obj2  //"32"
    b+obj3  //“33”
    
    a==obj2  //false
    a==obj1  //true

    最后提一个比较奇葩的题目。

    定义一个变量a,使得下面的表达式结果为true

      a == 1 && a == 2 && a == 3

    这里我简单提示下,a要是一个对象,重写valueOf方法,让它每次隐式转换的时候,调用时i++。

    프런트엔드 작성 test-JS 암시적 변환 문제의 함정

    valueOf()在Object上默认返回的是对象不是原始类型,它会再调用toString。所以只要重写toString也可以。

    如果还是没有思路,你们可以去看下这道题的文章原文从一道面试题说起—js隐式转换踩坑合集。

    推荐教程:《JS教程

    위 내용은 프런트엔드 작성 test-JS 암시적 변환 문제의 함정의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제