当前位置: 首页 > 科技观察

JS语法:问题由++[[]][+[]]+[+[]]=10

时间:2023-03-16 13:19:18 科技观察

解释:为什么++[[]][+[]]+[+[]]=10[0]是一个有0个成员的数组,而[0][0]取它的第一个成员,所以必须为0。虽然[0][0]='1'是用来改变第一个成员的值,接下来的[0][0]是取成员值的独立表达式,所以得到数字值0。[]=1是右值不可迭代(iterable)导致的错误。这应该是“解构赋值”导致的错误。不同浏览器调试://ChromeTypeError:undefineddisnotafunction//FirefoxTypeError:1isnotiterable//SafariTypeError:[]isnotafunction.(In'[]','[]'isundefined)如果数组被解构赋值,右值必须是可迭代的(可迭代)。下面例子中的错误和[]=1一样,所以应该是先检查右值是否可迭代时,先抛出类型错误:[]={};[]=undefined;[]=null;***,[]='1'不会导致错误,因为字符串是可迭代的(iterable)。JS中{}+{}和{}+[]的结果是什么?ToPrimitive内部操作所以加号运算符只能用于原始数据类型,那么如何将对象类型的值转换为原始数据类型呢?下面介绍如何转换为原始数据类型。在ECMAScript第6版#7.1.1中,有一个抽象的ToPrimitive操作,用于将对象转换为原始数据类型。该操作不仅会用在加号运算符中,还会用在关系比较或值相等比较中。中间。ToPrimitive的语法解释如下:ToPrimitive(input,PreferredType?)input表示代入的值,PreferredType可以是数字(Number)也可以是字符串(String),将代表“优先级”、“***”转换成哪种原始类型,转换步骤会根据此处的值而有所不同。但如果没有提供这个值,这是默认情况,转换的提示值将被设置为“默认”。原始转换类型的指示(提示值)是JS在做内部转换时根据情况自动加上的,一般是默认值。在JS对象原型的设计中,必须要有valueOf和toString这两个方法,所以这两个方法会存在于所有的对象中,只是在转换e的时候调用顺序可能会互换。当PreferredType为Number(Number)时当PreferredType为Number(Number)时,input为要转换的值,转换输入值的步骤如下:如果input为原始数据类型,则直接返回input。否则,如果input是一个对象,则调用该对象的valueOf()方法,如果可以得到原始数据类型的值,则返回该值。否则,如果input是一个对象,则调用该对象的toString()方法,如果可以得到原始数据类型的值,则返回该值。否则,将抛出TypeError错误。当PreferredType为字符串(String)时,上述2、3步骤相反。当不提供PreferredType时,即hint为“default”时,步骤与PreferredType为数字(Number)时相同。数字实际上是默认类型。也就是说,一般情况下,plus操作中的对象需要进行变换时,会先调用valueOf,再调用toString。但是有两个例外,一个是Date对象,一个是Symbol对象,它们覆盖了原有的PreferredType行为,Date对象的默认类型是字符串(String)。因此,你会看到在一些教程文件中,有两种类型的对象,一种是Date对象,另一种叫做non-Date(非日期)对象。因为这两种类型的对象都转换为原始数据类型,最大类型正好相反。模拟代码说明a+b:pa=ToPrimitive(a)pb=ToPrimitive(b)if(paisstring||pbisstring)returnconcat(ToString(pa),ToString(pb))elsereturnadd(ToNumber(pa),ToNumber(pb))JS对Object和Array的设计JS中设计的Object纯对象类型的valueOf和toString方法,返回值如下:valueOf方法返回值:对象本身。(所以ToPrimitive***应该返回toString的值)toString方法返回值:"[objectObject]"字符串值,不同内置对象的返回值为"[objecttype]"字符串,"type"指的是对象本身的类型标识,重要的是。例如,Math对象返回“[objectMath]”字符串。但是,一些内置对象在直接调用时没有这个值,因为它们覆盖了这个方法。(注:返回字符串前面的“object”英文开头是小写,后面开头的英文是大写)一元正号(+)有设置***类型的作用(即is,hint)为数字(Number),所以可以强制将对象转换为数字类型,一般对象会转换为:这里的***类型其实就是一个数字本身,+让字符串toString的输出被再次转换。>+{}//等价于+[objectObject]"NaN当然object的这两个方法是可以重写的,可以用下面的代码观察这两个方法的运行顺序,下面是先调用的caseofvalueOf:letobj={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->NaNconsole.log(''+obj);//valueOf->toString->'obj'实例基本类型运算字符串+其他原始类型字符串在加运算中有***优先权>'1'+123"1123">'1'+false"1false">'1'+null"1null">'1'+undefined"1undefined"数字+其他非字符串原始数据类型数字优先>1+true//true转1,false转02>1+null//null转为01>1+undefined//null转为NaNNaN非原数据类型的数字/字符串进行加法运算即转为数字再运算>true+true2>true+null1>undefined+nullNaN对象类型之间的操作Emptyarray+Emptyarray>[]+[]""两个数组相加仍然是valueOf->toString的顺序,但是因为valueOf是数组本身,所以会使用toString的返回值原来的数据类型是一个空字符串,所以这个操作相当于两个空字符串相加。根据加法运算规则第二步,是一个字符串拼接操作(concatenation),将两个空字符串拼接起来***返回空字符串。Emptyobject+Emptyobject特别注意:{}+{}在不同的浏览器中有不同的结果如果在第一个(前面)空对象后面加上括号(()),JS会认为前面是一个对象,可以得到同样的结果:>({})+{}"[objectObject][objectObject]"注意:上面提到的行为不是加操作的第一个(前面)对象字面量值一个空对象是无关紧要的,即使它是一个带有值的对象字面量,如{a:1,b:2},结果相同。Date对象>1+(newDate())>"1SunNov27201601:09:03GMT+0800(CST)"获取Date对象中valueOf的返回值,需要使用一元加号(+)强制转换为一个数字类型,比如下面的代码:>+newDate()1480180751492解构赋值引起的问题总结>{name:1}['name']='2'{name:1}['name']='2'^^^^^^SyntaxError:无效解构赋值目标错误。>{name:1}[name]='2''2'{name:1}[name]等同于{name:1};[name]。解构赋值成功。{}problem>varname='test'>{[name]:1}Object{1:1}>{[name]:1};[name]='1'VM174:1UncaughtSyntaxError:Unexpectedtoken:上面的错误其实是由于,{[name]:1}中的{}是一个表达式,返回一个对象;{[名称]:1};{}in[name]='1'是一个语句,语句中不允许有“[name]:1”,换句话说,语句中可以有“{name:1}”。{}+{}{}+{}的结果会因浏览器而异。在Chrome(v55)中,是一个objectObject字符串拼接,但其他浏览器认为它等同于+{}操作。返回NaN数字类型。{}+[]的结果相当于+[],结果是一个0数字类型。上面提到的Date对象Date对象是一个类型为“string”的异常对象,区别于其他对象(一般对象会先调用valueOf再调用toString),时不时会进行加操作优先使用toString进行转换,***必须是字符串拼接(concatenation)>1+(newDate())>"1SunNov27201601:09:03GMT+0800(CST)"toString()Object.prototype.toString()是用于检测变量本身的类型,typeof是检测基本类型,instanceof是检测是否在原型链上。(注意Object.prototype.toString不同于Number.prototype.toString和Array.prototype.toString)>vara=1undefined>a.toString()'1'>Number.prototype.toString.call(a)'1'>Object.prototype.toString.call([1,2])'[objectArray]'>Array.prototype.toString.call([1,2])'1,2'>[1,2].join()'1,2'toString方法返回值:“[objectObject]”字符串值,不同内置对象的返回值为“[objecttype]”字符串,“type”是指对象本身的类型标识,例如Math对象返回“[objectMath]”字符串。但是,一些内置对象在直接调用时没有这个值,因为它们覆盖了这个方法。(注:返回字符串中“object”开头为小写,后面开头为大写。>Object.prototype.toString.call(null)'[objectNull]'>typeofnull'object'>Object.prototype.toString.call(1)'[objectNumber]'Number()、String()和Boolean()常used比较混乱的是直接使用了Number()、String()和Boolean()这三个强制函数,这和wrapper对象的用法是不一样的。包装对象必须使用new关键字进行对象实例化,例如newNumber(123),Number('123')是一个将其他类型强制转换为数字类型的函数。