个人理解: this我们可以看成一个JavaScript为我们提供的"变量名", 它的指向问题就是它寻找自己变量的过程
1. this指向分析
根据红宝书上定义: this的指向取决于他运行时候的上下文,跟定义的时候没有关系.
- 简单的例子来看一下this的指向问题:
javascript
function foo() {
console.log(this)
}
foo() // window
从上面可以看出this不是指向引用他的函数,只能它运行时候
的上下文有关系.
2. this绑定的规则
<你不知道的JavaScript>定义: this的绑定和函数声明的位置没有任何关系, 之取决于函数的调用方式. 当一个函数被调用的时候,会创建一个活动记录(也称为执行上下文).
执行上下文(活动记录): 这个记录会包含函数在哪里被调用(调用栈),函数的调用方法,传入的参数等信息. this就是记录的其中的一个属性, 会在函数执行的过程中用到.
2.1默认绑定
默认绑定的情况下,全部指向Window
函数独自调用的情况就是默认绑定, this指向window
javascript
var f = function ()
console.log("foo函数:", this)
},
var obj = {
a : a
fn: fn
}
var b = obj.fn
b() // window
2.2隐式绑定
隐式绑定: 需要考虑是否被某个对象调用
javascript
function foo() {
console.log("foo函数:", this)
}
var obj = {
foo: foo,
}
//情况一: 隐式绑定
obj.foo() //obj
//情况二: 默认绑定
var bar = obj.foo
bar() // window
当然还有一种例外的情况就是隐式丢失:
在情况二中bar是obj.foo的一个引用, 但是实际上, 它是独立调用,因此它应用了默认绑定
.
2.3 显式绑定
显式绑定就是强制性绑定: 应用call()
, apply()
, bind()
这三种函数对this的指向进行强制性绑定.
javascript
function foo(a, b, c) {
console.log("foo函数:", this)
console.log("打印参数:", a, b, c)
}
//call绑定
foo.call("call", 10 , 20, 30)
//apply绑定
foo.apply("apply", [30, 20, 10])
//bind绑定
var bar = foo.bind("bind", 9, 8)
bar(7)
2.4 new绑定
在面向函数中"构造函数"是类的一种特殊方法,使用new
初始化类会调用类中的构造函数.
javascript
something = new MyClass(...)
在new
中this的绑定规则:
javascript
function foo() {
console.log("foo函数:", this)
}
new foo() //foo
在使用new
来调用 foo( ) 时,我们会构建一个新的对象绑定到 foo( ) 调用this上. 我们称之为 new 绑定.
3. this绑定的优先级
需要注意的是: new和call/apply无法一起使用,因此不能通过new foo.call来直接进行测试
new绑定 > 显式绑定(bind > call = apply) > 隐式绑定 > 默认绑定
4. 箭头函数
箭头函数里面没有this,但是可以使用this, 像寻找变量一个向上寻找,从而决定this的指向.
箭头函数并不是使用function关键字定义的,而是使用操作符 => 定义的, 箭头函数不使用this的四种规则, 而是根据外层(函数或者全局)作用域开决定this
4.1箭头函数
箭头的基本使用:
javascript
var foo3 = (name, age) => {
console.log(name, age)
}
4.2箭头函数中的this
javascript
// this的查找规则
var obj = {
name: "obj",
foo: () => {
var bar = () => {
console.log("bar:", this)
}
return bar
},
}
var fn = obj.foo()
fn() //window
fn.apply("bbb") //Window
因为箭头函数中没有this, 所以在箭头函数中使用this, this需要一层层作用域向上寻找this指向.
必须注意的是:
在浏览器环境中 obj{ }不是一个作用域,所以找到window,
但是在 Node.js 中,没有像浏览器那样的全局 Window
对象。当执行 fn()
时,bar
函数内部的 this
同样没有被显式绑定,此时 Node.js 会将 this
设置为一个空对象 {}
,这是 Node.js 环境下的默认行为。
本文为圈友 zChao 总结的学习文章