为什么要用this
this
提供了一种隐式传递
一个对象引用的方式,使得API设计的更加简洁并且易于复用。
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(me); // KYLE
identify(you); // READER
speak(me); // Hello, I'm KYLE
speak(you); // Hello, I'm READER
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, I'm KYLE
speak.call(you); // Hello, I'm READER
误解
this指向自身?
以下代码
count1
之所以打印0
,是因为此函数内部的this
指向的是window
,并不是函数本身
。
function foo() {
this.count1++; // this 实际上是window对象
arguments.callee.count2++; // 函数本身
}
// 存储循环次数
foo.count1 = 0;
foo.count2 = 0;
for (let i = 0; i < 6; i++) {
foo();
}
// 打印循环次数
console.log(foo.count1, foo.count2); // 0 6
arguments.callee 已经被弃用
,不建议使用,使用call
来改变this指向
// 使用call function foo() { console.log(this); // 改变了this指向之后的this指向了函数本身 this.count++; } // 存储循环次数 foo.count = 0; for (let i = 0; i < 6; i++) { foo.call(foo, null); // 改变了this指向,指向到了foo本身 } // 打印循环次数 console.log(foo.count); // 6
- 示例:
// n的结阶乘 n已知(请使用递归实现) function foo() { arguments.callee.res *= arguments.callee.n--; if (arguments.callee.n === 0 || arguments.callee.n === 1) { return arguments.callee.res; } return arguments.callee(); } foo.n = 5; foo.res = 1; // 存储阶乘结果 foo(); console.log(foo.res); // 120 foo.n = 10; foo.res = 1; // 存储阶乘结果 foo(); console.log(foo.res); // 3628800
// n的结阶乘 n已知(请使用递归实现) function foo() { this.res *= this.n--; if (this.n === 0 || this.n === 1) { return this.res; } return this.call(foo, null); } foo.n = 5; foo.res = 1; // 存储阶乘结果 foo.call(foo, null); console.log(foo.res); // 120 foo.n = 10; foo.res = 1; // 存储阶乘结果 foo.call(foo, null); console.log(foo.res); // 3628800
this指向函数的作用域?
this 在任何情况下都不指向函数的词法作用域。
function foo() {
var a = 2;
console.log(this); // {}
this.bar(); // this.bar is not a function
}
function bar() {
console.log(this, this.a); // 浏览器window undefined
}
foo.call({
}, null);
- 以上示例的错误:
- 因为
foo
中的this
指向的是{}
(在不同设备上this指向的环境不同
),所以找不到this.bar
,可修改为bar()
。 - 编者试图用
this
联通foo
和bar
的词法作用域
,从而在bar
中访问到a
变量,但实际上this
指向的还是设备环境
,所以a
还是找不到的。
- 因为
this到底是什么
this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this 就是记录的其中一个属性,会在函数执行的过程中用到。