# this
# 一般概念
今天我们了解一些 this 关键字, 在JS 中, this代指当前对象的引用,至于代指哪个当前对象,还要看 this 所在的函数的上下文来判断, 所以this也被称为函数上下文
我们可以做个不太形象的类别, this 和 中文语境下的 “这” 很像, 如下面的这段话
小明学会了穿裤子, 这让小明爸爸很高兴
上面这段话, 这 单独拿出来先来没有任何意义, 放在这个句子中,我们就知道, ‘这’代指小明学会穿裤子这件事
中文中有很多这种联系 上下文的 词语 , 比如 这 , 那 , 那个, 上面 …
我们不是在讨论中文语法, 所以这里不展开来讲
我们说这么多, 就是让大家更加形象的立即 this 在 js中的作用。
下面再举个简单的例子,看看 this的基本用法
<script>
var xiaoming = {
nickname: '小明',
sayHello: function() {
console.log('我是:',this.nickname);
}
}
xiaoming.sayHello();
</script>
上面由于是 xiaoming 对象调用了 syaHello() 方法, 所以 this 代指的就是 xiaoming 这个对象
再举个例子
因此此时已经脱离了 xiaoming 对象,默认有 window对象调用, 而window对象并没有nickname、age属性
<script>
var xiaoming = {
nickname: '小明',
sayHello: function() {
console.log('我是',this.nickname);
}
}
var sayHelloFun = xiaoming.sayHello;
sayHelloFun();
</script>
上面这个例子会输出我是 undefined
因为我们把 一个函数赋值给了另外一个函数, 随后 其实 是Window对象调用了 sayHelloFun(); 所以这里的 this代指的就是 Window对象, 而window对象没有 name 属性,所以这里会输出一个 undefined
由此我们得出一个结论:
- 同一个函数, 用不同的对象去调用他,this 指代的 对象不同
- 函数只有在被调用的时候,其中包含的this才会明确知道上下文
也就是说, 再普通语法中,谁调用了相关函数, this 就指向谁
# 数组内的this引用
数组内的this引用
我们都知道, 数组的元素是可以包含函数类型的
<script>
var array = ['A', 'B', function () {
console.log(this[0]);
}]
array[2]();
</script>
这个例子会输出A, 函数内部的 this 指向的是 数组本身, 因为最终是数组在调用数组内的元素
# 立即执行函数的this引用
<script>
var a = 1;
var obj = {
a: 2,
fun: (function() {
var a = this.a;
console.log(a + this.a);
return function() {
console.log(a + this.a);
}
})()
}
obj.fun();
</script>
上面的例子会输出2 ,紧接着输出3; 执行步骤如下
立即执行函数 在被解析到的时候就会立即执行
// 此时的this 指向 window, 立即执行函数的都是被 window 加载,所以指向他 a = 1 var a = this.a; // 此时输出2 console.log(a + this.a);
接着返回在一个函数,并将引用赋值 给 fun 句柄
return function() { // this : 谁调用我我指向谁 a = 1 console.log(a + this.a); }
接着 obj 在调用 fun() 的时候,返回值 函数的 this 指向 obj, 所以 , this.a 在这一刻明确为 2
// a = 1 , this.a = 2 , 最终结果: 3 obj.fun();
# setTimeout 等异步执行函数的this引用
<script>
var obj {
a: 1,
b: 2,
fun: function() {
console.log(this.a + this.b);
}
}
var a = 3;
var b = 4;
setTimeout(obj.fun, 200);
</script>
上面的这个例子会输出 7 ; 我们都知道 setTimeout 属于 window对象, 这里的 obj.fun (opens new window) 只是作为一个形参 传给了 setTimeout , 而真正执行调用的是Window对象
在看一个例子
<script>
var obj = {
a: 1,
b: 2,
fun: function() {
console.log(this.a + this.b);
}
}
var a = 3;
var b = 4;
setTimeout(obj.fun(), 2000);
</script>
这个例子, 实际是setTimeout的错误用法,
obj.fun() 在传参的时候因为加了‘()’就被执行了, 所以会打印出 3,我们实际上是把3传给了 setTimeout函数
此时的 setTimeout 没有发挥异步的作用
# call 和 apply
# 基本用法
我们前面讲了, 谁调用函数,this 就代指谁, 这个规律适用于类似于下面的这种调用语法
对象.函数()
而call、apply 可以改变 this的指向,他们的语法通常是这样
函数.call(对象, 函数所需参数1, 函数所需参数2, ....);
函数.apply(对象, 函数所需参数数组, 函数所需参数数组)
把哪个对象传入 call 和 apply函数中, this 就代表哪个对象
举例
<script>
function sum() {
alert(this.chinese + this.math + this.english);
}
var xiaoming = {
chinese: 80,
math: 95,
english: 83
}
// 函数.call(上下文)
// 函数.apply(上下文)
sum.call(xiaoming);
sum.apply(xiaoming);
</script>
# 两者区别
<script>
function sum(b1, b2) {
alert(this.chinese + this.math + this.english + b1 + b2);
}
var xiaoming = {
chinese: 80,
math: 95,
english: 83
}
// call 要用逗号罗列参数
sum.call(xiaoming, 1, 2);
// apply 要把参数写到数组中
sum.apply(xiaoming, [1, 2]);
</script>
使用call, 要把 原本函数所需的参数逐一罗列开; 使用 apply , 要把原有函数的参数封装到一个数组中