当前位置: 首页 > Web前端 > HTML5

javascript中你可能遇到的隐式调用

时间:2023-04-05 00:31:57 HTML5

前言不知道用隐式调用来形容是否准确。它的行为总是隐藏在背后,时不时就会显露出来。好像作用不大,但是理解还是有用的,保证在你的使用下大有作为。所谓隐式调用,简单来说就是自动调用一些方法,这些方法可以像钩子一样在外部进行修改,从而改变既定的行为。下面我将列出一些我最近看到的隐式调用。这些例子都是点对点的。欢迎添加数据类型转换toSting和valueOfvarobj={a:1,toString:function(){console.log('toString')return'2'},valueOf:function(){console.log('valueOf')返回3}}console.log(obj=='2');//output'valueOf'falseconsole.log(String(obj));//依次输出'toString''2'varobj={a:1,toString:function(){console.log('toString')返回'??2'},valueOf:function(){console.log('valueOf')return{}//修改为对象}}console.log(obj=='2');//output'valueOf''toString'trueconsole.log(Number(obj));//依次输出'valueOf''toString'2在相等运算符的运算中,对象会先调用valueOf。如果返回值是一个对象,它会调用toSting,除了null,然后使用返回值进行比较。第一个示例等同于3=='2'并输出false。在第二个例子中,通过执行valueOf返回一个对象,然后执行toString。最后,它等同于'2'=='2'并且输出为真。在Number和String方法中,Number会先调用valueOf,然后再调用toString,这在String方法中正好相反。除了上面两个例子,数据类型转换还存在于其他各种操作中,比如数值操作。当涉及到引用类型时,将调用valueOf或toString方法。只要是对象,都会继承这两个方法。我们可以重写这两个方法来影响数据类型转换的行为handleEventvareventObj={a:1,handleEvent:function(e){console.log(this,e);//返回DOM2事件告警中的eventObj和事件对象(this.a)}}document.addEventListener('click',eventObj)你没有看错,addEventListener的第二个参数除了可以是函数外,还可以是对象。事件触发后,会执行对象的handleEvent方法。当方法执行时This指向eventObj,可以将你要传入的数据绑定到eventObj对象JSON对象toJSONvarObj={a:10,toJSON:function(){return{a:1,b:function(){},c:NaN,d:-Infinity,e:Infinity,f:/\d/,g:newError(),h:newDate(),i:undefined,}}}console.log(JSON.stringify(对象));//{"a":1,"c":null,"d":null,"e":null,"f":{},"g":{},"h":"2018-02-09T19:29:13.828Z"}如果JSON的stringify方法传入的对象有toJSON方法,那么这个方法执行的对象会转换为toJSON执行后返回的对象。需要注意的一点是下面的代码varObj1={a:10,toJSON:function(){console.log(this===Obj1);//truereturnthis}}console.log(JSON.stringify(Obj1));//{"a":10}varObj2={a:10,toJSON:function(){console.log(this===Obj2);//truereturn{a:this}}}console.log(JSON.stringify(Obj2));//如果按照上面的说法报错Maximumcallstacksizeexceeded,很明显这个错误是我们预想的,但是当直接returnthis根本不报时,不妨大胆猜测一下内部toJSON返回的对象与原始对象之间的比较。如果相等就直接使用原对象的promise对象的thenvarobj={then:function(resolve,reject){setTimeout(function(){resolve(1000);},1000)}}Promise.resolve(obj).then(function(data){console.log(data);//输出1000,延迟1秒左右})Promise.resolve方法传入对象时,如果有then方法,则then方法会立即执行,相当于把方法放到一个新的Promise中,除了Promise.resolve有这个行为,Promise.all也有这个行为vartimePromise=function(time){returnnewPromise(function(resolve){setTimeout(function(){解析e(时间);},时间)})}vartimePromise1=timePromise(1000);vartimePromise2=timePromise(2000);vartimePromise3=timePromise(3000);Array.prototype.then=function(resolve){setTimeout(function(){resolve(4000);},4000)}Promise.all([timePromise1,timePromise2,timePromise3]).then(function(time){控制台.log(time);//等待大约4秒输出4000})对象属性访问器get和setvarobj={_age:100,getage(){returnthis._age<18?这个._age:18;},设置年龄(值){this._age=value;console.log(`年龄设置为${value}岁`);}}obj.age=1000;//年龄设置为1000obj.age=200;//年龄设置为200console.log(obj.age);//18obj.age=2;////年龄设置为2console.log(obj.age);//2可以看到不管我年龄怎么设置,我的年龄都是18岁以下,在进行属性访问的时候,其实是调用了对象属性对应的getset函数。除了上述写法外,还有以下写法:varinput=document.createElement('input');varspan=文档.createE元素(“跨度”);document.body.appendChild(输入);document.body.appendChild(跨度);varobj={_age:''}varobj=Object.defineProperty(obj,'age',{get:function(){returnthis._age;},set:function(value){this._age=value;输入.value=value;span.innerHTML=value;}});输入。onkeyup=function(e){if(e.keyCode===37||e.keyCode===39){返回;}obj.age=this.value}现在输入的值和obj.age的属性值span的innerHTML值绑定到TogetheriteratorinterfaceSymbol.iteratorvararr=[1,2,3];arr[Symbol.iterator]=function(){constself=this;让索引=0;return{next(){if(index