this的指向
全局作用域中的this
指向它本身
函数中的this
函数中this的指向,实在函数被调用的时候确定的
函数被调用时,会产生一个执行上下文,执行上下文被创建的时候会做几件事情:创建变量对象;确定作用域链,确定this指向
在函数执行过程中,this一旦被确定,就不可更改了
var name = "kaka";
var obj = { name: "lulu" };
function test1() {
this=obj // 报错 Uncaught SyntaxError: Invalid left-hand side in assignment
console.log(this.name);
}
test1();
普通函数
如果调用者函数,被某一个对象所拥有(作为对象的方法),那么该函数在调用时,内部的this指向该对象(函数的调用者)。如果函数独立调用,那么该函数内部的this指向undefined;再非严格模式下,当this指向undefined和null时,会被默认指向全局对象
var a = 20;
var obj = {
a: 10,
c: this.a + 20,
fn: function () {
// "use strict";
return this.a;
},
};
console.log(obj.c);
console.log(obj.fn());
var func = obj.fn;
console.log(func());
console.log(window.func());
在非严格模式下输出结果是:40 10 20 20
在严格模式下输出结果是:40 20 报错:undefined没有a属性 20(由于前面报错没有打印)
obj虽然有{},但是他并没有产生一个独立上下文,没有产生一个函数作用域,所以this指向是全局对象
构造函数
构造函数中的this指向实例对象
function Person(name, age) {
this.name = name;
this.age = age;
console.log(this); // {name:"潘周聃",age:29}
}
var p = new Person("潘周聃", 29);
箭头函数
箭头函数没有自己的this,this始终沿着作用域链向上找,它实在函数定义是确定的,而不是执行时,也就是箭头函数所在的执行上下文创建的时候,确定了箭头函数中this的指向
箭头函数中的this会保留在定义该函数时的上下文
King被调用的时候产生了一个上下文,箭头函数定义是在这个上下文中;所以这里的this指向实例对象
var name = "潘周聃,";
var content = "男,29岁";
function King(name, content) {
this.name = name;
this.content = content;
setTimeout(() => {
console.log(this.name + this.content); // 欧豪,", "你是我的神"
}, 0);
}
const k = new King("欧豪,", "你是我的神");
如果我们使用普通函数,this指向全局对象
var name = "潘周聃,";
var content = "男,29岁";
function King(name, content) {
this.name = name;
this.content = content;
setTimeout(function () {
console.log(this.name + this.content); // 潘周聃,男,29岁
}, 0);
}
const k = new King("欧豪,", "你是我的神");
再来一个例子
<div class="good">这是一个div</div>
const dom = document.getElementsByClassName("good")[0];
dom.addEventListener("click", () => {
console.log(this, "箭头函数"); // this指向全局对象Window
});
dom.addEventListener("click", function () {
console.log(this, "普通函数"); // this指向dom,函数的调用者
});
修改函数的this指向
call
fn.call(targetObj,param1,param2……)
var name = "kaka";
var obj = { name: "lulu" };
function test1() {
console.log(this.name);
}
test1.call(obj); // 控制台输出"lulu"
会自动执行一次函数,改变函数中的this指向;
参数以参数序列的形式传递,第一个参数是this要指向的对象,后面是函数的参数
var name = "kaka";
var obj = { name: "lulu" };
function test1(num1, num2) {
console.log(this.name); // lulu
console.log(num1 - num2); // 8
}
test1.call(obj, 10, 2);
apply
fn.apply(targetObj,[params])
? var name = "kaka";
? var obj = { name: "lulu" };
? function test1(num1, num2) {
? console.log(this.name); // lulu
? console.log(num1 - num2); // 8
? }
? test1.apply(obj, [10, 2]);
会自动执行一次函数,改变函数中的this指向
和bind一样,只是传递给函数的参数不一样,apply以数组的形式传参
bind
bind返回的是函数
// 这是错误的写法
var name = "kaka";
var obj = { name: "lulu" };
function test1(num1, num2) {
console.log(this.name); // kaka
console.log(num1 - num2); // NaN
}
test1.bind(obj, 10, 2);
test1();
因为test1函数中的this是在函数被调用的时候确定的,bind会返回一个函数,但是并没有调用函数;函数真正被调用的时候this指向undefined,非严格模式下指向全局对象,所以是打印kaka
bind不会自动调用一次函数,其他和call一样的
// 正确方式
var name = "kaka";
var obj = { name: "lulu" };
function test1(num1, num2) {
console.log(this.name); // lulu
console.log(num1 - num2); // 8
}
const bindFn = test1.bind(obj, 10, 2);
bindFn(); // 或者test1.bind(obj, 10, 2)();
|