• 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)
    

      

  • 相关阅读:
    微信小程序:模板消息推送提示{“errcode”:41030,”errmsg”:”invalid page hint: [gP1eXXXXXX]”}
    Linux 定时执行shell脚本命令之crontab
    Ubuntu16.04系统下 解决“无法获得锁 /var/lib/dpkg/lock -open (11:资源暂时不可用)、无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它?”的方法
    微信小程序:wx.request之post请求后端无法获取数据的问题
    jQuery获取浏览器参数
    Chrome等浏览器下出现net::ERR_BLOCKED_BY_CLIENT的解决办法
    Thinkphp3.2.3框架下封装公共的函数,例如封装CURL函数来获取接口数据
    Select下拉列表选择自动提交form表单数据
    一步一步从原理跟我学邮件收取及发送 5.C语言的socket示例
    一步一步从原理跟我学邮件收取及发送 4.不同平台下的socket
  • 原文地址:https://www.cnblogs.com/gengzhen/p/14088371.html
Copyright © 2020-2023  润新知