this的指向
在先看文章前,看看能不能把这些题给做出来
1 | var obj = { |
函数调用
JS(ES5)里面有三种函数调用形式
1 | fun() // 直接调用 |
一般,初学者都知道前两种形式,而且认为前两种形式「优于」第三种形式。
从看到这篇文章起,你一定要记住,第三种调用形式,才是正常调用形式:
1 | func.call(context, p1, p2) |
其他两种都是语法糖,可以等价地变为 call 形式:
1 | func(p1, p2) 等价于 |
至此我们的函数调用只有一种形式:
1 | func.call(context, p1, p2) |
这样,this 就好解释了
this,就是上面代码中的 context。就这么简单。
this 是你 call 一个函数时传的 context,由于你从来不用 call 形式的函数调用,所以你一直不知道。
先看 func(p1, p2) 中的 this 如何确定:
当你写下面代码时
1 | function func(){ |
用「转换代码」把它转化一下,得到
1 | function func(){ |
按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:
如果你传的 context 是 null 或 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)
因此上面的打印结果是 window。
如果你希望这里的 this 不是 window,很简单:
1 | func.call(obj) // 那么里面的 this 就是 obj 对象了 |
再看 obj.child.method(p1, p2) 的 this 如何确定
1 | var obj = { |
按照「转换代码」,我们将 obj.foo() 转换为
1 | obj.foo.call(obj) |
好了,this 就是 obj。搞定。
回到题目:
1 | var obj = { |
[ ] 语法
1 | function fn (){ console.log(this) } |
我们可以把 arr0 想象为arr.0( ),虽然后者的语法错了,但是形式与转换代码里的 obj.child.method(p1, p2) 对应上了,于是就可以愉快的转换了:
1 | arr[0]() |
Node-this的指向区别
由于NodeJs的运行环境不一样,完全脱离了浏览器,所以它的this
不是指向window
1 | function fun(){ |
use strict
在严格模式下,this
将保持他进入执行环境时的值,所以下面的this
将会默认为undefined
。
所以,在严格模式下,如果 this
没有被执行环境(execution context)定义,那它将保持为 undefined
。
Bom和Node环境下都是一样的
1 | function f2(){ |
修改this的指向
通过ES6的箭头函数修改
1 | document.querySelector("#app").onclick = function () { |
通过bind的修改
bind的作用:为前面的函数,修改函数内部的this指向,让函数内部的this,指向bind的参数列表中的第一个参数
注意:bind中的第一个参数,是用来修改this指向的,第一个参数后面的所有参数,都会当作将来调用前面函数时候的参数传递进去
bind并不会修改原函数,bind的函数会将改变了this指向的原函数作为返回值
bind和call/apply之间的区别
- call/apply修改完this指向后,会立即调用前面的函数,但是bind只是修改this指向,并不会调用
用法
Code1
2
3
4
5
6
7
8
9
10
11
12
13
14
function ww(){
conosle.log(this);
}
ww(); // window
document.getElementById("app").onclick = function(){
console.log(this); // app
ww = ww.bind(this);
}
ww(); // app使用方式
- 在事件处理函数中,直接使用bind绑定this并传参
- 绑定函数并接收返回值
apply
call
作为对象的方法
1 | var o = { |