溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JS語法中由 ++[[]][+[]]+[+[]] = 10引發(fā)的問題分析

發(fā)布時間:2021-11-15 15:14:08 來源:億速云 閱讀:119 作者:iii 欄目:web開發(fā)

本篇內容主要講解“JS語法中由 ++[[]][+[]]+[+[]] = 10引發(fā)的問題分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“JS語法中由 ++[[]][+[]]+[+[]] = 10引發(fā)的問題分析”吧!

解釋:為什么 ++[[]][+[]]+[+[]] = 10

[0]是一個帶有0成員的數(shù)組,[0][0]是取它的第1個成員,所以必是0。

用了[0][0] = '1'雖然改了第1成員的值,但下一個[0][0]是獨立的取成員值的表達式,所以得到0數(shù)字值。

[] = 1是右值不是iterable(可迭代的)造成的錯誤,這應該是”解構賦值”造成的錯誤,以不同的瀏覽器調試:

// Chrome TypeError: undefined is not a function   // Firefox TypeError: 1 is not iterable   // Safari TypeError: [] is not a function. (In '[]', '[]' is undefined)

數(shù)組解構賦值的話,右值必需是iterable(可迭代的),下面的例子的錯誤與[] =  1是一樣錯誤,所以應該會先檢查右值是否為iterable時,先拋出類型錯誤:

[] = {}; [] = undefined; [] = null;

***的,[] = '1'不會有錯誤,是因為字符串是屬于iterable(可迭代的)。

JS的{} + {}與{} + []的結果是什么?

ToPrimitive內部運算

因此,加號運算符只能使用于原始數(shù)據(jù)類型,那么對于對象類型的值,要如何轉換為原始數(shù)據(jù)類型?下面說明是如何轉換為原始數(shù)據(jù)類型的。

在ECMAScript 6th Edition  #7.1.1,有一個抽象的ToPrimitive運算,它會用于對象轉換為原始數(shù)據(jù)類型,這個運算不只會用在加號運算符,也會用在關系比較或值相等比較的運算中。下面有關于ToPrimitive的說明語法:

ToPrimitive(input,  PreferredType?)input代表代入的值,而PreferredType可以是數(shù)字(Number)或字符串(String)其中一種,這會代表”優(yōu)先的”、”***的”的要進行轉換到哪一種原始類型,轉換的步驟會依這里的值而有所不同。但如果沒有提供這個值也就是預設情況,則會設置轉換的hint值為”default”。這個***的轉換原始類型的指示(hint值),是在作內部轉換時由JS視情況自動加上的,一般情況就是預設值。

而在JS的Object原型的設計中,都一定會有兩個valueOf與toString方法,所以這兩個方法在所有對象里面都會有,不過它們在轉換e有可能會交換被調用的順序。

當PreferredType為數(shù)字(Number)時

當PreferredType為數(shù)字(Number)時,input為要被轉換的值,以下是轉換這個input值的步驟:

  1. 如果input是原始數(shù)據(jù)類型,則直接返回input。

  2. 否則,如果input是個對象時,則調用對象的valueOf()方法,如果能得到原始數(shù)據(jù)類型的值,則返回這個值。

  3. 否則,如果input是個對象時,調用對象的toString()方法,如果能得到原始數(shù)據(jù)類型的值,則返回這個值。

  4. 否則,拋出TypeError錯誤。

當PreferredType為字符串(String)時

上面的步驟2與3對調.

PreferredType沒提供時,也就是hint為”default”時

與PreferredType為數(shù)字(Number)時的步驟相同。

數(shù)字其實是預設的***類型,也就是說在一般情況下,加號運算中的對象要作轉型時,都是先調用valueOf再調用toString。

但這有兩個異常,一個是Date對象,另一是Symbol對象,它們覆蓋了原來的PreferredType行為,Date對象的預設***類型是字符串(String)。

因此你會看到在一些教程文件上會區(qū)分為兩大類對象,一類是 Date 對象,另一類叫 非Date(non-date)  對象。因為這兩大類的對象在進行轉換為原始數(shù)據(jù)類型時,***類型恰好相反。

模擬代碼說明

a + b:     pa = ToPrimitive(a)     pb = ToPrimitive(b)       if(pa is string || pb is string)        return concat(ToString(pa), ToString(pb))     else        return add(ToNumber(pa), ToNumber(pb))

JS對于Object與Array的設計

在JS中所設計的Object純對象類型的valueOf與toString方法,它們的返回如下:

valueOf方法返回值: 對象本身。(所以ToPrimitive***要返回toString的值了)

toString方法返回值: “[object Object]”字符串值,不同的內建對象的返回值是”[object  type]”字符串,”type”指的是對象本身的類型識別,例如Math對象是返回”[object  Math]”字符串。但有些內建對象因為覆蓋了這個方法,所以直接調用時不是這種值。(注意:  這個返回字符串的前面的”object”開頭英文是小寫,后面開頭英文是大寫)

一元正號(+),具有讓***類型(也就是hint)設置為數(shù)字(Number)的功能,所以可以強制讓對象轉為數(shù)字類型,一般的對象會轉為:

這里***類型其實本身就是數(shù)字,+讓toString輸出的字符串再強轉了一次。

> +{} //相當于 +"[object Object]" NaN

當然,對象的這兩個方法都可以被覆蓋,你可以用下面的代碼來觀察這兩個方法的運行順序,下面這個都是先調用valueOf的情況:

let obj = {   valueOf: function () {       console.log('valueOf');       return {}; // object   },   toString: function () {       console.log('toString');       return 'obj'; // string   } } console.log(1 + obj);  //valueOf -> toString -> '1obj' console.log(+obj); //valueOf -> toString -> NaN console.log('' + obj); //valueOf -> toString -> 'obj'

實例

基本類型間運算

字符串 + 其他原始類型字符串在加號運算有***的優(yōu)先運算

> '1' + 123 "1123"   > '1' + false "1false"   > '1' + null "1null"   > '1' + undefined "1undefined"

數(shù)字 + 其他的非字符串的原始數(shù)據(jù)類型數(shù)字為優(yōu)先

> 1 + true //true轉為1, false轉為0 2   > 1 + null //null轉為0 1   > 1 + undefined //null轉為NaN NaN

數(shù)字/字符串以外的原始數(shù)據(jù)類型作加法運算就是轉為數(shù)字再運算

> true + true 2   > true + null 1   > undefined + null NaN

對象類型間運算

  • 空數(shù)組 + 空數(shù)組

> [] + []  ""

兩個數(shù)組相加,依然按照valueOf ->  toString的順序,但因為valueOf是數(shù)組本身,所以會以toString的返回值才是原始數(shù)據(jù)類型,也就是空字符串,所以這個運算相當于兩個空字符串在相加,依照加法運算規(guī)則第2步驟,是字符串連接運算(concatenation),兩個空字符串連接***得出一個空字符串。

  • 空對象 + 空對象

特別注意: {} + {}在不同的瀏覽器有不同結果

如果在***個(前面)的空對象加上圓括號(()),這樣JS就會認為前面是個對象,就可以得出同樣的結果:

> ({}) + {} "[object Object][object Object]"

注: 上面說的行為這與加號運算的***個(前面)的對象字面值是不是個空對象無關,就算是里面有值的對象字面,例如{a:1, b:2},也是同樣的結果。

  • Date對象

> 1 + (new Date())  > "1Sun Nov 27 2016 01:09:03 GMT+0800 (CST)"

要得出Date對象中的valueOf返回值,需要使用一元加號(+),來強制轉換它為數(shù)字類型,例如以下的代碼:

> +new Date()  1480180751492

總結

解構賦值產(chǎn)生的問題

> {name: 1}['name'] = '2' {name: 1}['name'] = '2'           ^^^^^^ SyntaxError: Invalid destructuring assignment target

上述錯誤。

> {name: 1}[name] = '2'  '2'

{name: 1}[name]相當于{name: 1};[name]。解構賦值成功。

{}問題

> var name = 'test' > {[name]:1} Object {1: 1} > {[name]:1};[name] = '1' VM174:1 Uncaught SyntaxError: Unexpected token :

上述錯誤其實是由于,{[name]:1}中{}是表達式,返回對象;{[name]:1};[name] =  ‘1’中{}是語句,語句中不允許”[name]:1“,換而言之語句中允許”{name: 1}”寫法。

{} + {}

{} + {}的結果是會因瀏覽器而有不同結果,Chrome(v55)中是object  Object字符串連接,但其它的瀏覽器則是認為相當于+{}運算,得出NaN數(shù)字類型。

{} + []的結果是相當于+[],結果是0數(shù)字類型。

Date對象

Date對象上面有提及是***類型為”字符串”的一種異常的對象,這與其他的對象的行為不同(一般對象會先調用valueOf再調用toString),在進行加號運算時時,它會優(yōu)先使用toString來進行轉換,***必定是字符串連接運算(concatenation)

> 1 + (new Date()) > "1Sun Nov 27 2016 01:09:03 GMT+0800 (CST)"

toString()

Object.prototype.toString()才是用來檢測變量本身的類型,typeof是檢測基本類型,instanceof是檢測是否在原型鏈上。(注意一下Object.prototype.toString與Number.prototype.toString、Array.prototype.toString不同)

> var a = 1 undefined > a.toString() '1' > Number.prototype.toString.call(a) '1' > Object.prototype.toString.call([1, 2]) '[object Array]' > Array.prototype.toString.call([1, 2]) '1,2' > [1, 2].join() '1,2'

toString方法返回值: “[object Object]”字符串值,不同的內建對象的返回值是”[object  type]”字符串,”type”指的是對象本身的類型識別,例如Math對象是返回”[object  Math]”字符串。但有些內建對象因為覆蓋了這個方法,所以直接調用時不是這種值。(注意:  這個返回字符串的前面的”object”開頭英文是小寫,后面開頭英文是大寫。

> Object.prototype.toString.call(null) '[object Null]' > typeof null 'object' > Object.prototype.toString.call(1) '[object Number]'

Number()、String()與Boolean()

常被搞混的是直接使用Number()、String()與Boolean()三個強制轉換函數(shù)的用法,這與包裝對象的用法不同,包裝對象是必須使用new關鍵字進行對象實例化的,例如new  Number(123),而Number(‘123’)則是強制轉換其他類型為數(shù)字類型的函數(shù)。

到此,相信大家對“JS語法中由 ++[[]][+[]]+[+[]] = 10引發(fā)的問題分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

js
AI