不同环境下的不同指向
- 透彻认识
function的this在不同的调用环境下的指向- 事件调用环境
- 全局环境
- 函数内部
- 箭头函数中的
this指向
事件调用环境
定义一个块元素 点击触发时向右移动100px
<body>
<div id="box"></div>
</body>
<script>
box.onclick = function() {
this.style.left = "100px";
};
</script>
函数中的 this 为触发事件的元素
全局环境(浏览器)
全局环境(浏览器) this 指向 window
函数内部
"use strict";
function add() {
console.log(this);
}
// 非严格模式下 调用定义的函数 函数内部的 this 指向 window
// 严格模式下 调用定义的函数 函数内部的 this 指向 undefined
add(); // undefined
// 严格模式下 调用 window.fn() 可以使函数内部的 this 指向 window
window.add(); // window
"use strict";
let obj = {
a: 10,
fn() {
console.log(this.a);
},
b: {
fn() {
console.log(this.a);
}
}
};
// 最终指向的是调用它的对象
obj.fn(); // 10
// 多层调用 指向的也只是上一层级的对象
obj.b.fn(); // undefined
// 此时调用fn方法的是 newObj 。严格模式下 this 指向的是 undefined
let newObj = obj.fn;
newObj(); // 报错
function Add(x) {
this.x = x;
console.log(this);
}
// 调用 new 大概进行的操作
// 1:调用函数 2:创建对象 3:将对象与this绑定 4:如果没有定义返回值 隐式返回this对象
let add = new Add(5); // {x: 5}
"use strict";
function Add(x) {
this.x = x;
console.log(this);
// 基础类型的都不会有影响
// null 特殊对象也不会有影响
return null;
}
let add = new Add(5); // {x: 5}
console.log(add); // {x: 5}
"use strict";
function Add(x) {
this.x = x;
console.log(this);
// 返回的是对象时 返回值为定义的对象值
return [];
}
let add = new Add(5); // {x: 5}
console.log(add); // []
结论:
-
this 最终指向的是调用它的对象
-
函数如果被多成对象包含,如果被函数最外层调用,this 指向的也只是上一层级的对象
-
构造函数中的 this 指向的是实例对象,如果构造函数返回的不是对象,this 保持不变 否则会被更改。 null 也属于对象 但不是有影响
箭头函数中的this
回到最初的例子 点击块元素 延时一秒执行函数
"use strict";
box.onclick = function() {
// 此时的写法是不对的 因为此时函数内的 this 指向为 window
setTimeout(function() {
console.log(this); // window
this.style.left = "100px";
}, 1000);
// 相当于 setTimeout(window.fn, 1000);
};
箭头函数绑定的是定义时上一层作用域的 this
box.onclick = function() {
// 箭头函数绑定的是定义时的上一层作用域
setTimeout(() => {
console.log(this);
this.style.left = "100px";
}, 1000);
};
"use strict";
let obj = {
fn: () => {
console.log(this);
},
fn2() {
console.log(this);
}
};
// 绑定的是上一层作用域 但对象不能形成独立的作用域
obj.fn(); // window
obj.fn2(); // obj 对象
- 箭头函数本身是没有 this 和 arguments 的,在箭头函数中引用的 this 实际上调用的是定义时的上一层的作用域的 this
- 这里强调一下,对象是不能形成独立的作用域的
修改 this 指向
apply、call、bind
"use strict";
let person = {
age: 18
};
let obj = {
fn: (x, y) => {
console.log(this.age, x, y);
},
fn2(x, y) {
console.log(this.age, x, y);
}
};
// 使用箭头函数 this 绑定的是定义时的作用域 所以无法修改
obj.fn.call(person, 1, 2); // undefined 1 2
// 调用 call 方法修改
obj.fn2.call(person, 1, 2); // 18 1 2
// 调用 apply 方法修改 参数为数组
obj.fn2.apply(person, [1, 2]); // 18 1 2
// 调用 bind 方法修改 bind 返回的是一个函数
obj.fn2.bind(person)(1, 2); // 18 1 2