1. this 关键字
在JS里面,每一个函数内部都有一个关键字 this,语法就是它本身,我们可以直接使用它。
但是:函数内部的this只和函数的调用方式有关,和函数的定义方式没有关系。 并且在函数内部this指向谁,完全取决于函数的调用方式。
- 全局定义的函数直接调用
function foo() {
console.log(this);
}
// 此时this就指向了Window
foo();
- 对象内部的方式调用,此时谁调用函数,
this就指向谁
let obj = {
foo: function () {
console.log(this);
}
}
// 此时this指向obj
obj.fn();
- 定时器的处理函数
setTimeout(function () {
console.log(this)
}, 1000)
// 此时定时器处理函数里面的 this 指向 windo
- 事件处理函数
div.onclick = function () {
console.log(this)
}
// 当你点击 div 的时候,this 指向 div,也就是说this指向了事件源
- 自调用函数
(function () {
console.log(this)
})()
// 此时 this 指向 window
我们再来看另外一种情况,虽然Car是首字母大写的函数,看起来像构造函数,但是因为在调用的时候,没有使用new关键字;所以就没有人帮你做4件事情:
创建 {}this => {}{key : value}return {key : value}
所以就当成普通函数来调用,普通函数默认返回undefined
由于普通函数是由window隐式帮我们调用,所以普通函数中的this指向window对象
<script>
function Car(color, brand){
this.color = color;
this.brand = brand;
};
var c1 = new Car('蓝色', 'benz');
console.log(c1);// undefined
function Car(color, brand){
// 1. 创建一个空对象
var me = {};
// 2. 将me作为this来使用,添加属性和方法
me.color = color;
me.brand = brand;
// 3. 将完成了属性挂载的对象返回出去
return me;
}
var c1 = Car('蓝色','benz');
console.log(c1);
var c2 = Car('red', 'BMW')
console.log(c2)
</script>
哪除了函数的基本调用的this指向之外,能不能改变this指向的方法呢?答案是可以的
2. this对象的转换
2.1 call
call方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向。
语法:
函数名.call(要改变的this指向,要给函数传递的参数1,要给函数传递的参数2,.......);
var obj = { name: 'tom' }
function fn(a, b) {
console.log(this);
console.log(a);
console.log(b);
}
fn(1, 2);
fn.call(obj, 1, 2);
以这段代码为例,函数的调用fn()的时候,函数内部的this指向Window。
而在fn.call(obj,1,2);时,函数内部的this就指向了obj这个对象。
使用call方法的步骤:
- 会立即执行函数
- 第一个参数是你要改变的函数内部的
this指向 - 第二个参数开始,依次向函数传递参数
2.2 apply
apply方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向。
语法:
函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...]);
var obj = { name: 'tom' }
function fn(a, b) {
console.log(this);
console.log(a);
console.log(b);
}
fn(1, 2);
fn.call(obj, [1, 2]);
函数在fn()的时候,函数内部的 this 指向 window。
fn.apply(obj, [1, 2]) 的时候,函数内部的 this 就指向了 obj 这个对象。
使用 apply 方法的步骤:
- 会立即执行函数
- 第一个参数是你要改变的函数内部的
this指向 - 第二个参数是一个
数组,数组里面的每一项依次是向函数传递的参数
2.3 bind
bind 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向。
和 call / apply 有一些不一样,就是不会立即执行函数,而是返回一个已经改变了 this 指向的函数。
语法:
var newFn = 函数名.bind(要改变的 this 指向); newFn(传递参数)
var obj = { name: 'tom' }
function fn(a, b) {
console.log(this);
console.log(a);
console.log(b);
}
fn(1, 2);
var newFn = fn.bind(obj);
newFn(1, 2);
bind在调用的时候,不会执行 fn 这个函数,而是返回一个新的函数。
这个新的函数就是一个改变了 this 指向以后的 fn 函数。
fn(1, 2)的时候 this 指向 window。
newFn(1, 2)的时候执行的是一个和 fn 一摸一样的函数,只不过里面的 this 指向改成了 obj。