引言
开发过程中,我们经常会用到this,this我理解是一个指针,指向堆中地址的引用,在不同情况下它会有不同的指向,针对浏览器环境下的this指向做一个总结。
全局环境下
console.log(this); // Window 对象
// 非严格模式
function fn() {
console.log(this); // Window 对象
}
fn();
// 严格模式
"use strict"
function fn() {
console.log(this); // undefined
}
fn();
构造函数
function Dog(name,age) {
this.name = name;
this.age = age;
console.log(this);
}
// 作为构造函数使用时 this指向创建出来的实例
let black = new Dog('black', 3);
let yellow = new Dog('yellow', 2);
// 作为普通函数使用时 this指向Window
let red = Dog('red', 5);
对象中使用
let obj = {
name: '前端小菜鸟',
getName: function() { return this.name }
}
console.log(obj.getName()) // 前端小菜鸟 指向当前对象
// 赋值给变量
let query = obj.getName;
console.log(query()); // Window 对象
定时器中
setTimeout(function() {
console.log(this); // Window 对象
},10)
setInterval(function() {
console.log(this); // Window 对象
},1000)
箭头函数
// 全局环境下
(()=> {console.log(this)})(); // Window 对象
// 作为对象的属性
let obj = {
name: '前端小菜鸟',
getName: () => this.name
}
console.log(obj.getName()) // Window 对象
特殊情况 对象方法中定时器结合箭头函数
箭头函数中的This取值取决于外部非箭头函数的this的值,且箭头函数中的this值无法更改(call、apply、bind)
// setTimeout中是普通函数
let obj = {
name: '前端小菜鸟',
getName: function () {
setTimeout(function() {
console.log(this) // Window 对象
},10)
}
}
obj.getName()
// setTimeout中是箭头函数
let obj = {
name: '前端小菜鸟',
getName: function () {
setTimeout(() => {
console.log(this) // obj
},10)
}
}
obj.getName()
事件绑定
var btn = document.getElementById("btn");
btn.onclick = function() {
console.log(this); // btn this 指向 绑定事件的对象
}
原型中
Array.prototype.getLenth = function () {return this.length };
[1,2,3].getLenth(); // 3
总结 谁调用指向谁! 不知道指向谁就说是Window
补录: 默认绑定 隐式绑定 显式绑定 new绑定
- 默认绑定-this指向的都是Window
- 隐式绑定-就是谁调用指向谁
- 显式绑定-就是用call、apply、bind改变this指向这种比较明显知道指向谁
- new绑定-this指向创建出来的实例
绑定优先级
- 显式绑定 > 隐式绑定 > 默认绑定
- new绑定 > 隐式绑定 > 默认绑定
不存在显式绑定 和 new绑定同时生效的情景,如果同时写这两种代码会直接抛错,所以没法比较
function Fn(){
this.name = '前端小菜鸟';
console.log(this.name);
};
let obj = {
name:'大菜鸟'
}
new Fn().call(obj); //报错 call is not a function