你不知道的js之this
this
为什么需要 this ?
来看一下下面两段代码
先看不使用 this 的
function identify(context) {
return context.name.toUpperCase();
}
function speak(context) {
var greeting = "Hello, I'm " + identify(context);
console.log(greeting);
}
var me = {
name: "Kyle"
};
var you = {
name: "Reader"
};
identify(you); // READER
speak(me); //hello, 我是 KYLE
再看使用 this 的
function identify() {
return this.name.toUpperCase();
}
function speak() {
var greeting = "Hello, I'm " + identify.call(this);
console.log(greeting);
}
var me = {
name: "Kyle"
};
var you = {
name: "Reader"
};
identify.call(me); // KYLE
identify.call(you); // READER
speak.call(me); // Hello, 我是 KYLE
speak.call(you); // Hello, 我是 READER
也就是说 this 提供了一种更优雅的方式来隐式“传递”一个对象引用,是我们的代码可以更加灵活和易于维护
this 不是什么?
this 不一定指向函数自身
this 指向函数的作用域。这个问题有点复杂,因为在某种情况下它是正确的,但是在其他情况下它却是错误的,需要明确的是,this 在任何情况下都不指向函数的词法作用域,在 JavaScript 内部,作用 域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过 JavaScript 代码访问,它存在于 JavaScript 引擎内部。
this 是什么?
- this 是在运行时进行绑定
- this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式
- 当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包 含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this 就是记录的 其中一个属性,会在函数执行的过程中用到
this 绑定规则
默认绑定:
首先要介绍的是最常用的函数调用类型: 独立函数调用,也就是默认绑定。可以把这条规则看作是无法应用其他规则时的默认规则。
function foo() {
console.log(this.a);
}
var a = 2;
foo(); // 2
需要注意的是,默认绑定在严格模式下会无效
隐式绑定
隐式绑定需要考虑的规则是调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
需要注意的是隐式绑定丢失
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
var a = "oops, global"; // a 是全局对象的属性
setTimeout(obj.foo, 100); // "oops, global"
JavaScript 环境中内置的 setTimeout() 函数实现和下面的伪代码类似:
function** setTimeout(fn,delay) {
// 等待 delay 毫秒
fn(); // <-- 调用位置!
}
显式绑定
通过 call、apply、bind 进行绑定
new 绑定
通过 new 关键字创建新实例时进行的 this 绑定
this 绑定的优先级
new > 显式绑定 > 隐式绑定 > 默认绑定
⚠️ 如果你把 null 或者 undefined 作为 this 的绑定对象传入 call、apply 或者 bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。
比如
function foo() {
console.log(this.a);
}
var a = 2;
foo.call(null); // 2
------------- 本文结束 感谢阅读 -------------