javascript this指向

在一些笔试题和项目中经常会出现一些this指向的问题。特此记录一下

this的默认指向

1.全局环境下this指向window
console.log(this) //window
2.函数独立调用,函数内部的this也指向window
3.被嵌套的函数独立调用时,this默认指向了window
        function fn1(){
            console.log(this); //window
        }
        fn1() //fn1() === window.fn1(),所以指向了window
        var a = 1;
        var obj = {
            a:2,
            foo:function(){
                // 函数当作对象的方法来调用时候,this指向obj
                var a = 3;
                var that = this;
                console.log(that.a) //2
                function test(){
                    console.log(this.a); //1
                }
                test()
            }
        }
        obj.foo() //独立函数调用指向window
                      
 4.IIFE 自执行函数(自执行函数默认指向window,跟函数内部调用一致)
        var a = 10;
        var obj = {
            a:2,
            foo:function(){
                console.log(this); //函数当作对象的方法来调用时候,this指向obj
                (function test(){
                    console.log(this.a);
                })()  //自执行函数默认指向window,跟函数内部调用一致
            }
        }
        obj.foo() // 10

        var a = 10;
        var obj = {
            a:2,
            foo:function(){
                console.log(this); //函数当作对象的方法来调用时候,this指向obj
                (function test(that){
                    console.log(that.a);
                })(this)  //自执行函数默认指向window,跟函数内部调用一致
            }
        }
        obj.foo() // 2    
5.闭包 :this默认指向了window
        var a = 0;
        var obj = {
            a:2,
            foo:function(){
                return function test(){
                    return this.a //闭包 :this默认指向了window
                }
            }
        }
        var bb = obj.foo()
        console.log(bb()) //0
            

6.隐式绑定

//当函数当作方法来调用,this指向了直接对象
function foo(){
    console.log(this.a)
}
var obj = {
    a:1,
    foo:foo,
    obj2:{
        a:2,
        foo:foo
    }
}
// foo()函数的直接对象是obj,this的指向指向了直接对象
obj.foo(); //1
obj.obj2.foo(); //2

7.隐式丢失

//隐式丢失就是指被隐式绑定的函数丢失了绑定对象,从而默认绑定到window
// 这种情况就是比较容易出错却又非常常见

一、隐式丢失:函数别名

var a = 0;
function foo(){
    console.log(this.a)
}
var obj = {
    a:1,
    foo:foo
}
// 把obj.foo()赋值给别名bar,造成隐式丢失的情况,因为只是把obj.foo()赋值了给了bar变量,而bar与obj对象毫无关系
var bar = obj.foo;
bar(); //0 
相当于
var a = 0;
var bar = function foo(){
    console.log(this.a)
}
bar()

二、参数传递

// 2.参数传递
var a = 0;
function foo(){
    console.log(this.a)
}
function bar(fn){
    fn()
}
var obj = {
    a:1,
    foo:foo
}
// 把obj.foo当作参数传递到bar函数中,有隐式的函数复制fn = obj.foo, 只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window
bar(obj.foo) //0
等价于
var a = 0;
function bar(fn){
    fn()
}
bar(function foo(){
    console.log(this.a);
})

三、内置函数

// 3.内置函数 setTimeout()和setInterval()第一个参数的回调函数中的this默认指向了window,跟第二种情况是类似
var a = 0;
function foo(){
    console.log(this.a)
}
var obj = {
    a:1,
    foo:foo
}
setTimeout(obj.foo,1000) //0 window

四、间接调用

// 4。间接调用
function foo(){
    console.log(this.a)
}
var a = 0;
var obj = {
    a:1,
    foo:foo
}
var p = {a:4}
// obj.foo(); //1
// // 立即调用
// // 将obj.foo函数对象赋值给p.foo函数,然后立即执行。相当与仅仅是foo()函数的立即调用,内部的this默认指向了window
// (p.foo = obj.foo)() //0
p.foo = obj.foo
// 将obj.foo赋值给p.foo函数,之后p.foo()函数再执行,其实是属于p对象的函数的指向,this指向当前的p对象
p.foo() //4

五、其他情况

//5.其他情况(指向了window的特殊情况)
function foo(){
    console.log(this.a)
}
var a = 0;
var obj = {
    a:1,
    foo:foo
}
// 都是立即执行函数,指向window
(obj.foo = obj.foo)() //0
(false || obj.foo)()  //0
(1,obj.foo)() //0

8.显示绑定

一、call() apply() bind() 

// call() apply() bind() 把对象绑定到this上,叫做显示绑定
var a = 0;
function foo(){
    console.log(this.a);
}
var obj = {
    a:2
}
foo() //0 window.foo()
foo.call(obj) //2
foo.apply(obj) //2
var fn = foo.bind(obj) //2 
fn()
二、硬绑定是显示绑定的一个变种,使得this不能再被改变
var a = 0;
function foo(){
    console.log(this.a);
}
var obj = {
    a:2
}
var bar = function(){
    foo.call(obj)
}
setTimeout(bar,2000) //2
bar.call(window) //2

三、 数组的forEach(fn,对象) //map() filter() some() every()第二个参数改变this指向

// 数组的forEach(fn,对象) //map() filter() some() every()第二个参数改变this指向
var id = 'window';
var obj = {
    id:'fn'
}
var arr = [1,2,3]
arr.forEach(function(el,index){
    console.log(el,index,this);
},obj) 
9.new绑定
function Fn() {
    //如果是new关键来执行函数,相当于构造函数来实例化对象,那么内部的this指向了当前实例化的对象 
    console.log(this); //Fn {}
}
var fn = new Fn()
console.log(fn); //Fn {}

function Fn2(){
    // this还是指向了当前的对象
    console.log(this);
    // 使用return关键来返回对象的时候,实例化出来的对象是当前的返回对象
    return {
        name:'zhen'
    }
}
var fn2 =new Fn2() //Fn2 {}
console.log(fn2) // {name: "zhen"}

var Person ={
    fav:function(){
        return this
    }
}
var p = new Person.fav();
console.log(p); //fav {}
console.log(p===Person.fav); //false
// 实例化出来的对象内部的属性constructor属性指向了当前的构造函数
console.log(p.__proto__.constructor === Person.fav);

 10.严格模式下this指向

//1.独立调用的函数内部的this指向了undefined
    function fn(){
        'use strict'
        console.log(this);
    }
    fn() //undefined
    //2.严格模式下,函数apply()和call()内部this始终是他们的第一个参数
    var color = 'red';
    function showColor(){
        'use strict'
        console.log(this.color);
    }
    showColor.call(undefined)

  

原文地址:https://www.cnblogs.com/gengzhen/p/14088371.html