js类型调换的各个玩的方法,关于js类型调换骚操

前言

本文是lhyt本人原创,希望用老妪能解的章程来精通一些细节和困难。转发时请申明出处。小说最先出现于自身github

对于object和number、string、boolean之间的变换关系

0.前言

js身为一种弱类型的言语,不用像c语言这样要定义int、float、double、string等等数据类型,因为允许变量类型的隐式转换和同意强制类型转变。我们在概念三个变量的时候,就二个var、let、const解决,不用操心数据的品类。比如大面积的字符串拼接,用+号可以兑现变量和字符串的拼凑。

由此看来,平时的平整是

!后边的字符会被转为换布尔

+前边的字符会被改变为数值(-也是大略)

[]+前面包车型地铁字符会被更动为字符串

对于object和number、string、boolean之间的转变关系,这里偷英特网一幅图

图片 1

Object 与Primitive,需要Object转为Primitive

String 与 Boolean,须求五个操作数同一时候转为Number。

String/Boolean 与 Number,需要String/Boolean转为Number。

undefined 与 null ,和全体其余值相比较的结果都以false,他们中间==成立

ToPrimitive是指转变为js内部的原始值,借使是非原始值则转为原始值,调用valueOf()和obj.toString()来得以实现。valueOf重回对象的值:在调整台,当您定义一个对象按回车,调整台打字与印刷的是Object{...},obj.toString()重返对象转字符串的花样,打字与印刷的是"[object Object]"

若果参数是Date对象的实例,那么先toString()假使是原始值则赶回,不然再valueOf(),如若是原始值则赶回,不然报错。

假定参数不是Date对象的实例,同理,可是先valueOf再obj.toString()。

  • [ ] Object 与Primitive,需要Object转为Primitive
  • [ ] String 与 Boolean,需求五个操作数同一时间转为Number。
  • [ ] String/Boolean 与 Number,需要String/Boolean转为Number。
  • [ ] undefined 与 null ,和具有其余值比较的结果都是false,他们之间==创建

1.奇葩例子

![] //false;

+[] // 0

+![] // 0

[]+[] // ""

{}+{}//"[object Object][object Object]"

{}+[]//0

{a:0}+1 // 1

[]+{}//"[object Object]"

[]+![]//"false"

{}+[]//0

![]+[] // "false"

''+{} //"[object Object]"

{}+'' //0

[]["map"]+[] //"function map() { }"

[]["a"]+[] // "undefined"

[][[]] + []// "undefined"

+!![]+[] //"1"

+!![] //1

1-{} //NaN

1-[] //1

true-1 //0

{}-1 //-1

[]==![] //true

ToPrimitive是指调换为js内部的原始值,假使是非原始值则转为原始值,调用valueOf()和toString()来完毕。valueOf重返对象的值:在调控台,当你定义四个目的按回车,调控台打字与印刷的是Object{...},toString()重临对象转字符串的款型,打字与印刷的是"[object Object]"

2.从[]==![]开始

大家也说不定据他们说过[]!=[],重如果因为她俩是引用类型,内部存储器地址区别所以不等于。那么为啥加了三个!就会等于了?不是内部存储器地址依旧不均等啊?

那又引出贰个难题,符号的前期度

  1. [] ()

2 ++ — ~ !

3 * / %

4 + - +

5 <<  >> 

6 + - +

7 < <= > >=

8 + - +

9 ==  !=  ===  !==

能够望见,!优先度是第二,所以先决断!再判断=

给[]取反,会是布尔值,[]的取反的布尔值就是false

  • [ ] 假若参数是Date对象的实例,那么先toString()要是是原始值则赶回,不然再valueOf(),假若是原始值则赶回,否则报错。
  • [ ] 如若参数不是Date对象的实例,同理,可是先valueOf再toString()。

2.1 []的反就是false?

ECMA规范:

非布尔类型转布尔类型:undefined、null 、0、±0、NaN、0长度的字符串=》false,对象=》true

非数字类型转数字类型:undefined=》NaN,null=》0,true=》0,false=》1,字符串:字符串数字一贯转数字类型、字符串非数字=》NaN

[]也是目的类型(typeof [] == "object"),转为布尔类型的![]就是false

1.局地例子

2.2 等号两侧相比

大家知晓,在相比较类型的时候,先会举办丰富多彩的类型调换。

从上马的报表能够望见,他们比较的时候都以先转移为数字类型。左侧是布尔值false,右侧为一个空数组对象,对于右边,先实行P操作(ToPrimitive([])),先执行valueOf([])再次来到的是[],非原始类型,再

[].toString(),再次来到的是"",那P操作之后,结果就是""了

最后,侧面""和侧边false相比,他们再调换为数字,正是0==0的难题了

在浏览器调整台输入一些各类运算符的构成,会合世有的有意思的结果:

3.从已有些获得想不到的

![] //false; +[] // 0 +![] // 0[]+[] // ""{}+{}//"[object Object][object Object]"{}+[]//0{a:0}+1 // 1[]+{}//"[object Object]"[]+![]//"false"{}+[]//0![]+[] // "false"''+{} //"[object Object]"{}+'' //0[]["map"]+[] //"function map() { }"[]["a"]+[] // "undefined"[][[]] + []// "undefined"+!![]+[] //"1"+!![] //11-{} //NaN1-[] //1true-1 //0{}-1 //-1[]==![] //true

3.1 直接获取数组方法

我们清楚,数组有自身的一套方法,例如var arr = [1,2];arr.push(1),我们得以写成[1,2].push(1),还足以写成[1,2]['push'](1),那么前边抛出的难题就化解了

[]['push'](1)//[1]

[]["map"] //function map() { [native code] }

[]["map"]+[] // "function map() { [native code] }"

2.从[]==![]开始

3.2 直接实行下标操作

咱俩领悟,[]!=[],首若是因为他们是引用类型,内部存款和储蓄器地址不一致所以不等于。那么为啥加了一个!就能够划上等于号了

3.2.1数字的获取

大家能够通过类型转变,得到0和1三个数字,既然能得到那多少个数字,那么也足以博得任何的全体数字了:

+[] === 0; +!![] === 1

那么, +!![]+!![] ===2,+((+![])+(+!![])+[]+(+![]))===10(注意:中间没[]的话,便是数字的1+0,结果就是1了,有的话正是'1'+''+'0')

+((+![])+(+!![])+[]+(+![]))-!![] ===9

差不离正是才高意广

标识的预先度能够参照mdn上的这几个汇总表格: 能够瞥见,[]==![]本条境况下先判定!再决断= 给[]取反,会是布尔值,[]的取反的布尔值便是false

3.2.2 字符串下标

(![]+[])[+[]] //"f"

(![]+[])[+!![]] // "a"

(![]+[])是"false",其实(![]+[])[+[]] 就一定于"false"[0],第三个假名,便是f

我们就足以从地点的这些获得单词的字符串获得其中的假名了

好了,说道这里,假诺何人说前端轻松,那就给他二个(![]+[])[+!![]+!![]+!![]] +([]+{})[+!![]+!![]]

2.1 []的反正是false?

4.关于(a==1 && a==2 && a==3)

普遍的片段退换:非布尔类型转布尔类型:undefined、null 、0、±0、NaN、0长度的字符串=》false,对象=》true 非数字类型转数字类型:undefined=》NaN,null=》0,true=》1,false=》0,字符串:字符串数字一直转数字类型、字符串非数字=》NaN

4.1 ==

近年有人问这一个主题材料(a==1 && a==2 && a==3) 或许(a===1 && a===2 && a===3) 能或不可能为true?

实际是可以的,正是因为在==比较的场合下,会开展项指标隐式转换。后边早就说过,如若参数不是Date对象的实例,就能够进展类型转变,先valueOf再obj.toString()

由此,大家只要改造原生的valueOf方法就能够达到效果:

var a = {

num: 0,

valueOf: function() {

return this.num += 1

}

};

var eq = (a==1 && a==2 && a==3);

console.log(eq);

每三次开展等号的可比,就可以调用一遍valueOf方法,自增1,所以能创设。当然,假使换个岗位就非常了,var eq = (a==2 && a==1 && a==3);

除此以外,减法也是同理:

var a = {

num: 4,

valueOf: function() {

return this.num -= 1

}

};

var eq = (a==3 && a==2 && a==1);

console.log(eq);

回到[]==![]的主题材料上,[]也是目的类型(typeof [] == "object"),转为布尔类型的![]就是false

4.2 ===

若是未有类型调换,===的情景,依然得以的。跑题...

在vue源码达成双向数据绑定中,就采纳了defineProperty方法开展察看,观望到视图层的变动并实时反映到model层。

每二遍访问对象中的某多少个属性的时候,就可以调用这些方式定义的指标里面包车型地铁get方法。每二回变动指标属性的值,就能够访谈set方法

在这里,大家相濡相呴定义本人的get方法:

var b = 1

Object.defineProperty(window, 'a', {

get:function() { return b++; }

})

var s = (a===1 && a===2 && a === 3 )

console.log(s)

每贰次访问a属性,a的属性值就能够+1,当然依然调换个方式置就无法为TRUE了

最先的小说来自lhyt的github

2.2 等号两侧相比较

我们领悟,在相比类型的时候,先会进行各式各样的类型调换。 从初步的表格能够看到,他们相比较的时候都以先转移为数字类型。右侧是布尔值false,侧边为二个空数组对象,对于右边,先举办ToPrimitive操作,先实行valueOf回到的是[],非原始类型,再 [].toString(),再次回到的是"",那ToPrimitive操作之后,结果正是""了 最终,左边""和侧边false相比,他们再退换为数字,正是0 == 0的标题了

3.更加多游戏的方法

3.1 直接获取数组方法

咱们通晓,数组有自个儿的一套方法,比方var arr = [1,2];arr.push,大家得以写成[1,2].push,还可以写成[1,2]['push'],那么后边抛出的主题素材就化解了

[]['push'] //[1][]["map"] //function map() { [native code] }[]["map"]+[] // "function map() { [native code] }"

3.2 直接实行下标操作

3.2.1数字的得到

咱俩能够通过类型转换,获得0和1几个数字,既然能获取那多个数字,那么也能够拿走任何的全数数字了: +[] === 0; +!![] === 1 那么,+!![]+!![] ===2,+++[]+===10

那就是说10-1=9也就来了: +++[]+-!![] ===9 简直正是德高望重

3.2.2 字符串下标

[+[]] //"f"[+!![]] // "a"

是"false",其实[+[]] 就一定于"false"[0],第一个字母,就是f 大家就足以从地点的那个获得单词的字符串得到当中的假名了,举个例子:[+!![]+!![]+!![]] +[+!![]+!![]]

调整基本套路后,大家能够轻巧发挥,在浏览器的调整台输入一些标识的重组,然后回车看一下我们写的“密码”会转变到什么

([][[]] + [])[(+!![] + [] + [] + +![] ) >> +!![]] +$$[~~[]].nodeName[- ~ -+~[]] +(this + [])[+!![]+[] + +[] - !!{} - !!{}] +[+!!{} << +!![] -~[]] +[+!![] -~[]]

4. 八个面试题

已经碰着五个那系列型的面试题:

4.1 (a==1 && a==2 && a==3) 能或不可能为true

(a==1 && a==2 && a==3)或者(a===1 && a===2 && a===3) 能否为true? 事实上是足以的,正是因为在==相比的景况下,交易会开项指标隐式调换。前面已经说过,假诺参数不是Date对象的实例,就能够开展类型调换,先valueOfobj.toString() 所以,我们只要改造原生的valueOf也许tostring方法就能够达到效果:

var a = { num: 0, valueOf: function() { return this.num += 1 }};var eq = (a==1 && a==2 && a==3);console.log;//或者改写他的tostring方法 var num = 0;Function.prototype.toString = function(){ return ++num;}function a(){}//还可以改写ES6的symbol类型的toP的方法var a = {[Symbol.toPrimitive]: (function  { return function(){return ++i } }) };

每三次实行等号的比较,就能调用二遍valueOf方法,自增1,所以能创建。 另外,减法也是同理:

var a = { num: 4, valueOf: function() { return this.num -= 1 }};var res = (a==3 && a==2 && a==1);console.log;

别的,若无类型转变,是 === 的可比,照旧得以的。 在vue源码达成双向数据绑定中,就使用了defineProperty方法开展考查数据被更换的时候,触发set。 每贰次访谈对象中的某壹性子质的时候,就能够调用那几个措施定义的对象里面的get方法。每一遍变动目的属性的值,就能够会见set方法 在此间,大家温馨定义自个儿的get方法:

var b = 1Object.defineProperty(window, 'a', { get:function() { return b++; }})var s = (a===1 && a===2 && a === 3 )console.log

每贰次访谈a属性,a的属性值就能够+1,当然依然交流地点就不可能为TRUE了

4.2 完善Cash打字与印刷五个101

务求只可以在class里面扩张代码:

class Cash {}const a = new Cashconst b = new Cashconsole.log(`${a.add},${Cash.add},${new Cash // 101,101,101

第一,几个出口结果是以隐式转变的款型现身的,那是非同一般之处。 a和b都以new出来的靶子,由new Cash能够看看构造函数字传送入的也是四个Cash的实例对象。那么new出来的结果断定不是简轻易单的三个object,不然就是被转变到'[object Object]',不过你又不得不以object类型出现,那就只能魔改隐式转变用到的toString和valueOf

class Cash { constructor  { this.m = a // 缓存真正的值 this.valueOf = function () { console.log return a } } add  { // a.add return this.m + $ } toString () { // 隐式转换调用 return this.m } static add  { //Cash.add return v1 + v2 }}

最后

但是,实际项目中五个数据作相比的时候,我们尽量不要写以至完全不用写多个等号,应该写三个等号,况兼js也稳步有向强类型过渡的自由化。

本人是致力了三年的前端程序员,不菲人偷偷问笔者,二〇一五年前端该怎么学,方法有未有?

科学,年底自己花了三个多月的岁月整理出来的求学资料,希望能帮忙你急速学习前端,拿高薪offer!

倘让你照旧在编制程序的社会风气里隐隐,不知底本身的未来布署,能够加入web前端学习沟通群:731771211 里面可以与大神一起交流并走出迷茫。新手可进群无偿领取学习资料,看看前辈们是什么样在编制程序的社会风气里傲然前行!群里不停更新最新的学科和读书情势(进群送web前端系统学习路径,详细的前端项目实战教学摄像),有想学学web前端的,或是转行,或是博士,还应该有职业中想提高自个儿技巧的,正在读书的小伙伴应接加入

点击:加入

本文由365bet体育在线官网发布于网络工程,转载请注明出处:js类型调换的各个玩的方法,关于js类型调换骚操

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。