JS基础篇:9、不同情况下的this指向

544 阅读2分钟

引言

开发过程中,我们经常会用到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绑定

  1. 默认绑定-this指向的都是Window
  2. 隐式绑定-就是谁调用指向谁
  3. 显式绑定-就是用call、apply、bind改变this指向这种比较明显知道指向谁
  4. new绑定-this指向创建出来的实例

绑定优先级

  • 显式绑定 > 隐式绑定 > 默认绑定
  • new绑定 > 隐式绑定 > 默认绑定

不存在显式绑定 和 new绑定同时生效的情景,如果同时写这两种代码会直接抛错,所以没法比较

function Fn(){
    this.name = '前端小菜鸟';
    console.log(this.name);
};
let obj = {
    name:'大菜鸟'
}
new Fn().call(obj); //报错 call is not a function