几条规则确定函数里的这个是什么。
想确定这是什么其实非常简单。总体的规则是,通过检查它的调用位置,在函数被调用的的时候确定。它遵循下面这些规则,接下来以优先级顺序说明。
1,如果在调用函数时使用新关键字,那么函数里的这就是一个全新的对象。
函数ConstructorExample () { console.log(这个); 这一点。值=https://www.yisu.com/zixun/10; console.log(这个); } 新ConstructorExample ();//-> {}//->{值:10}
2,如果使用,电话或者绑定调用函数,那么函数里的这就是作为参数传进去的对象。
函数fn () { console.log(这个); } var obj={ 值:5 }; var boundFn=fn.bind (obj); boundFn ();//鷞值:5} fn.call (obj);//鷞值:5} fn.apply (obj);//鷞值:5}
3,如果函数作为一个方法调用,就是说如果使用点符号调用函数,那这就么是拥有这个函数作为属性的对象。换句话说,当一个点在函数调用的左侧时,这就是这个点左侧的那个对象。
var obj={ 值:5 printThis:函数(){ console.log(这个); } }; obj.printThis ();//鷞值:5,printThis: & # 402;}
4,如果函数作为一个纯粹的函数调用,也就是说,它在没有上述任何条件的情况下被调用,那这就么是全局对象。在浏览器里,就是窗口对象。
函数fn () { console.log(这个); }//如果在浏览器里调用: fn ();//翱趝站:& # 402;开放:& # 402;,警报:& # 402;,…}
注意这个规则其实和第三个规则是一样的,区别在于没有声明为方法的函数会自动成为全局对象窗口的属性,因此,这其实是一个隐式的方法调用。当我们调用fn(),其实就会被浏览器理解为window.fn(),所以这就是窗口。
控制台。日志(fn===window.fn);//嬲?/pre>5,如果上述规则有多个适用,那么优先级更高的就会设置值。
6,如果是ES2015里的箭头函数,那么它将忽略上述所有规则,并在创建的时候接收包含它的作用域作为这样的值。想确定这具体是什么的话,只需从创建箭头函数那里往上一行,看看那儿的这是什么,箭头函数里的这个值和它一样。
const obj={ 价值:“abc”, createArrowFn:函数(){ 返回()=比;console.log(这个); } }; const arrowFn=obj.createArrowFn (); arrowFn ();//鷞值:“abc”, createArrowFn: & # 402;}看回第三个规则,当我们调用obj.createArrowFn()的时候,createArrowFn里的这个是obj,因为这是方法调用。因此,obj会在arrowFn里绑定到这上。如果我们在全局作用域创建一个箭头函数,那么这个值就会是窗口。
让我们来看一个代码示例,并应用这些规则。尝试一下看能否弄清楚不同的函数调用下,这是什么。
<强>确定应用了哪条规则强>
var obj={ 价值:“嗨”, printThis:函数(){ console.log(这个); } }; var=obj.printThis打印; obj.printThis ();//鷞值:“嗨”,printThis: & # 402;} print ();//翱趝站:& # 402;开放:& # 402;,警报:& # 402;,…}obj.printThis()属于第三条规则,方法调用。另一方面,print()属于第四条规则,纯粹的函数调用。对于打印()来说,我们在调用的时候没有使用新的绑定/电话/应用或者点符号,所以它对应了规则四,这就是全局对象窗口。
当适用多个规则的时候,使用列表里更高优先级的规则。
var其中obj1={ 价值:“嗨”, 打印:函数(){ console.log(这个); }, }; var methoda={值:17};如果规则二和规则三同时适用,那么规则二占优。
obj1.print.call methoda ();//鷞值:17}如果规则一和规则三同时适用,那么规则一占优。
新obj1.print ();//鷞}
有些库有时候会故意将这个值绑定到某些函数里。而通常会在函数里将最有用的值绑定到这上使用。举个例子,jQuery把这个绑定到DOM元素上,在回调中触发一个事件。如果某个库出现一个不太符合上述规则的这个值,那么请仔细阅读这个库的文档,它很有可能使用绑定绑定了。
JavaScript中的这个简单规则