首頁 >web前端 >js教程 >前端筆試中的坑位-JS隱式轉換問題

前端筆試中的坑位-JS隱式轉換問題

hzc
hzc轉載
2020-06-17 10:00:321994瀏覽

我們在寫筆試題的時候,常常碰到涉及隱式轉換的題目,例如

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

=== 和==

===#叫做嚴格運算符,物件類型指向位址相同或原始型別( 數值、字串、布林值)值相同;==叫做相等運算符,型別不同會進行轉換再比較,undefined、null相等,物件類型還是比較引用。 ==運算子將​​原始值和其包裝物件視為相等,但===運算子將​​它們視為不等。 所有obj.a==null(相當於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
  • #ToNumber規則

    • null=> 0
  • undefined => NaN

#"123" =>123  "12ssd"=>NaN  ""=>0

false => 0    true=>1

###數組、物件Toitive######true=>1######陣列、物件Toitive####### ###########ToBoolean規則############js中七個falsy 值(虛值) 為false,其他都為true######### #######隱含轉換######有了對上面知識點的認識,我們可以來一舉拿下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++。

前端筆試中的坑位-JS隱式轉換問題

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

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

推荐教程:《JS教程

以上是前端筆試中的坑位-JS隱式轉換問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除