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

FE.ES-理解ECMAJavascript的this

时间:2023-04-05 23:43:51 HTML5

this其实就是调用函数时发生的绑定,它指向什么完全取决于调用函数的地方(即函数的调用方法)。四个规则:(你不知道的JS)1.默认绑定函数foo(){console.log(this.a);}vara=2;foo();//2无论是否在严格模式下,在全局执行上下文中(在任何函数体之外)this指的是全局对象。(MDN)在严格模式下,这将保留它进入执行上下文时的值,如果执行上下文未定义它,则为未定义。(MDN)functionfoo(){“使用严格”;console.log(this.a);}vara=2;foo();//类型错误:这是未定义的2。当函数作为对象时隐式绑定/丢失当调用方法时,它们的this是调用函数的对象,并且绑定仅受最接近的成员引用的影响。(MDN)//隐式绑定函数foo(){console.log(this.a);}varobj2={a:42,foo:foo};varobj1={a:2,obj2:obj2};obj1.obj2.foo();//42//隐式损失functionfoo(){console.log(this.a);}functiondoFoo(fn){//fn实际上是指foofn();//<--调用位置!}varobj={a:2,foo:foo};vara="oops,global";//a是全局对象的一个??属性doFoo(obj.foo);//"oops,global"3.显示绑定如果要将this的值从一个上下文传递到另一个上下文,请使用call或apply方法。(MDN)调用f.bind(someObject)会创建一个与f具有相同主体和作用域的函数,但在这个新函数中,this永久绑定到bind的第一个参数,无论函数是如何调用的。varobj={count:0,cool:functioncoolFn(){if(this.count<1){setTimeout(functiontimer(){this.count++;//这是安全的//因为bind(..)console.日志(“更棒”);}.bind(这个),100);//看,bind()!}}};obj.cool();//更棒。硬绑定创建一个包装函数,它接受所有参数并返回接收到的所有值。硬绑定会大大降低函数的灵活性。使用硬绑定后,您不能使用隐式绑定或显式绑定来修改this。//简单的辅助绑定函数functionbind(fn,obj){returnfunction(){returnfn.apply(obj,arguments);};}软绑定为默认绑定指定了一个全局对象和一个非undefined的值,那么就可以达到和硬绑定一样的效果,同时保留隐式绑定或显式绑定修改this的能力。Function.prototype.softBind=function(obj){varfn=this;varcurried=[].slice.call(arguments,1);//捕获所有柯里化参数varbound=function(){returnfn.apply((!this||this===(window||global))?obj:这个curried.concat.apply(curried,arguments));};bound.prototype=Object.create(fn.prototype);返回绑定;};4。new绑定当一个函数被用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象上。(MDN)使用new来调用一个函数,或者当调用构造函数时,会自动执行下面的操作(你不懂的JS)来创建(或构造)一个全新的对象。这个新对象将通过[[prototype]]连接执行。这个新对象将绑定到函数调用的this。如果函数没有返回其他对象,那么new表达式中的函数调用将自动返回这个新对象。functionfoo(a){this.a=a;}varbar=newfoo(2);console.log(bar.a);//2四条规则优先newbinding>explicitbinding>implicitbinding判断>defaultboundfunctioncalledinnew(newbinding)?如果是这样,这将绑定到新创建的对象。varbar=newfoo()函数是通过call、apply(显式绑定)还是硬绑定调用的?如果是这样,则将其绑定到指定的对象。另外:如果绑定为null或undefined,则实际应用默认绑定规则。varbar=foo.call(obj2)函数是否在某些上下文对象中被调用(隐式绑定)?如果是这样,则this将绑定到该上下文对象。varbar=obj1.foo()如果两者都不是,则使用默认绑定。如果在严格模式下绑定到undefined,否则绑定到全局对象。varbar=foo()其中:间接引用函数将应用默认绑定规则functionfoo(){console.log(this.a);}vara=2;varo={a:3,foo:foo};varp={a:4};o.foo();//3(p.foo=o.foo)();//2个例外1.箭头函数箭头函数没有使用this的四个标准规则,而This是根据外部(函数或全局)作用域来确定的。在箭头函数中,this与封闭词法上下文的this相同。(MDN)箭头函数继承封闭函数调用的this绑定(不管this绑定到什么)。这其实和self=this是一样的机制。不能修改箭头函数绑定。2.nodejssetTimeout(function(){console.log(this)//Browser:window//nodejs:Timeoutinstance},0)其他说明https://www.zhihu.com/questio...func(p1,p2)等同于func.call(undefined,p1,p2)obj.child.method(p1,p2)等同于obj.child.method.call(obj.child,p1,p2)如果你传递了上下文为null或undefined,则window对象为默认上下文(在严格模式下,默认上下文为undefined)。例子varnumber=50;varobj={number:60,getNum:function(){varnumber=70;返回这个。数字;}};警报(obj.getNum());警报(obj.getNum.call());alert(obj.getNum.call({number:20}));参考资料:深入理解JavaScript系列(13):本?是的,这个!-FangYinghang-知乎JS这个相关问题