美文网首页
你知道多少this,new,bind,call,apply?那我

你知道多少this,new,bind,call,apply?那我

作者: 魔王哪吒 | 来源:发表于2019-11-14 02:44 被阅读0次

    那么什么是this,new,bind,call,apply呢?这些你都用过吗?掌握这些内容都是基础中的基础了。如果你不了解,那还不赶快去复习复习,上网查阅资料啥的!

    通过call,apply,bind可以改变this的指向,this指向一般指向它的调用者,默认挂载在window对象下。es6中的箭头函数中,this指向创建者,并非调用者。

    const func = function () {
        console.log(this);
        const func2 = function () {
          console.log(this);
        };
        func2(); //Window
      };
      func(); //Window
    
    'use strict'
      const func = function () {
        console.log(this);
        const func2 = function () {
          console.log(this);
        };
        func2(); //undefined
      };
      func(); //undefined
    
    var a = 2
    
    var obj = {
        a: 4,
        foo:() => {
            console.log(this.a)
        
            function func() {
                this.a = 7
                console.log(this.a)
            }
        
            func.prototype.a = 5
            return func
        }
    }
    
    var bar = obj.foo()        
    // 浏览器中输出: 2
    bar()                      
    // 浏览器中输出: 7
    new bar()                  
    // 浏览器中输出: 7
    

    一般函数方法中使用this指向全局对象:

    function test(){
       this.x = 1
      console.log(this.x)
    }
    
    test()  
    // 1
    

    作为构造函数调用,this指向new实例化的对象:

    function test(){
      this.x = 1
    }
    
    var o = new test()
    alert(o.x)  
    // 1
    

    第一,this的学习,需要掌握哪些呢?this最重要的就是其指向的类型,那么在JavaScript中应该如何确定this的指向呢?

    this是在函数被调用时确定的,它的指向完全取决于函数调用的地方,而不是它被声明的地方。(除了箭头函数)记住一点:this始终指向调用它的对象,对象中的方法中的this,指向调用它的对象。

    var obj = {
     a: 1,
     b: {
      a: 2,
      func: function() {
       console.log(this.a); // 输出结果为2
       console.log(this); // 输出结果是b对象
      }
     }
    }
    
    // 调用
    obj.b.func();
    
    var obj = {
     a: 1,
     b: {
      func: function() {
       console.log(this.a); // undefind
       console.log(this); // b对象
      }
     }
    }
    
    // 调用
    obj.b.fun();
    

    改变调用方法,不直接调用:

    var obj = {
     a: 1,
     b: {
      a: 2,
      func: function() {
       console.log(this.a); // undefined 若在对象obj外定义a,则输出的就是其在外定义的值
       console.log(this); // window
      }
     }
    }
    
    var j = obj.b.func; 
    // 只是将b对象下的方法赋值给j,并没有调用
    j(); 
    // 调用,绑定的对象是window,并非b对象直接调用
    

    在绝大多数情况下,函数的调用方式决定了this的值,this不能在执行期间被赋值,并且在每次函数被调用时this的值也可能会不同。this指向的对象称为函数的上下文对象context,this的指向取决于函数被调用的方式。

    function foo() {
     console.log(this);
    }
    

    那么我来问你?this指向哪里?哈哈哈,应该时不知道吧,因为谁调用指向谁,函数都没被调用,确实不知道指向。

    function foo() {
     console.log(this);
    }
    // window全局对象
    > undefined
    
    // obj对象
    var obj = {
     foo: foo
    }
    obj.foo();
    > {foo:f}
    

    直接通过函数名来调用函数,this指向全局变量window,通过对象,函数名调用函数,this指向该对象。当一个函数被调用的时候,会创建一个执行的上下文,它包含函数在哪里被调用,函数的调用方式,传入的参数等信息。

    this的使用场景:

    作为构造函数被new调用,作为对象的方法使用,作为函数直接调用,被call,apply,bind调用,箭头函数中的this。

    基础:函数内部this指向问题:

    var myObj = {
     foo: "bar",
     func: function() {
      var self = this;
      console.log(this.foo);
      console.log(self.foo);
      (function() {
       console.log(this.foo);
       console.log(self.foo);
      }());
     }
    }
    
    myObj.func();
    

    结果:

    bar
    bar
    undefined
    bar
    

    在对象方法中调用时:

    var location = {
     x: 0,
     y: 0,
     move: function(x,y) {
      this.x = this.x + x;
      this.y = this.y + y;
      console.log(this.x); // 1
      console.log(this.y); // 1
     }
    };
    
    location.move(1,1) 
    // this绑定到当前对象,即为location对象
    

    作为函数调用时:

    function func(x) {
     this.x = x;
    }
    
    func(2); 
    // 函数被调用时,this绑定的时全局对象window,相当于直接声明了一个全局变量x
    console.log(x); 
    // x已经成为一个值为5的全局隐式变量
    

    对象中this的指向问题:

    var a = 1;
    
    function printA() {
     console.log(this.a);
    }
    
    var obj = {
     a: 2,
     foo: printA,
     bar: function() {
      printA();
     }
    }
    
    obj.foo(); // 2
    obj.bar(); // 1
    var foo = obj.foo;
    foo(); // 1
    
    

    this的指向不是函数声明时绑定的,而是在函数运行过程中动态绑定的。

    前端笔试:

        function a(xx) {
            this.x = xx;
            return this;
        }
    
        var x = a(5);
        var y = a(6);
    
        console.log(x.x);    //undefined
        console.log(y.x);    //6
    
    file

    基础:new绑定,显式绑定,隐式绑定,默认绑定,this绑定的优先级,箭头函数中的this。

    箭头函数中的this是根据其声明的地方来决定this的,它是ES6中出现的知识点,箭头函数中的this,是无法通过call,apply,bind被修改的,且因箭头函数没有构造函数constructor,导致也不能用new调用,就不能作为构造函数了,否则会出现错误。

    箭头函数不能arguments,super,this或new.target定义本地绑定。箭头函数中对arguments,super,this或new.target的任何引用都解析为当前所在词法作为域中的绑定,通常,这就是箭头函数所在函数作用域。

    this在不同场景中的指向:

    // 匿名函数中的this指向全局对象
    var a = 2;
    
    var func = {
     a: 4,
     fn: (function() {
      console.log(this); // window
      console.log(this.a); // 2
     })()
    }
    
    // setInterval和setTimeout定时器中的this指向全局对象
    var a = 2;
    
    var oTimer = setInterval(function(){
     var a = 3;
     console.log(this.a); // 2
     clearInterval(oTimer);
    },100);
    
    // eval中的this指向调用上下文中的this
    (function() {
     eval("console.log(this)"); // window
    })();
    
    function Foo() {
     this.bar = function(){
      eval("console.log(this)"); // Foo
     }
    }
    
    var foo = new Foo();
    foo.bar();
    
    // apply 和 call中的this指向参数中的对象
    var a = 2;
    
    var foo = {
     a: 20,
     fu: function(){
      console.log(this.a);
     }
    };
    
    var bar = {
     a: 200
    }
    
    foo.fu.apply(); // 2(若参数为空,默认指向全局对象)
    foo.fu.apply(foo); // 20
    foo.fu.apply(bar); // 200
    

    this绑定的优先级:优先级:new绑定 > 显示绑定 > 隐式绑定 > 默认绑定

    new绑定:函数中有new的调用,this绑定的是新创建的对象
    显示绑定:函数中有bind,apply,call调用,this绑定的是指定的对象
    隐式绑定:函数中是否在某个上下文对象调用,this绑定的是那个上下文对象
    默认绑定:在严格模式下,就绑定到undefined,否则绑定到全局对象

    new绑定:函数使用new调用时,this绑定的是新创建的构造函数的实例

    function func() {
     console.log(this)
    }
    
    var bar = new func() 
    // func实例,this就是bar
    

    重点,创建一个新对象,构造函数的prototype被赋值给这个新对象的proto,将新对象赋给当前的this,执行构造函数,如果函数没有返回其他对象,那么new表达式中的函数会自动返回这个新对象。

    显示绑定:call,apply,bind可以用来修改函数绑定的this

    function fn (name, price){
     this.name = name
     this.price = price
    }
    
    function Food(category, name, price) {
     fn.call(this, name, price) // call方式调用
     // fn.apply(this, [name,price]) // apply方式调用
     this.category = category
    }
    
    new Food('水果','苹果','6');
    

    call和apply的区别:

    call方法接受的是参数列表
    apply方法接受的是参数数组

    fu.call(this, arg1, arg2, ...) // call
    
    fu.apply(this, [arg1,arg2, ...]) // apply
    
    func.bind(thisArg[, arg1[, arg2[, ...]]])    
    // bind 用法
    

    隐式绑定:函数是否在某个上下文对象中调用,如果是,this绑定的是那个上下文对象。

    var a = 'hello5'
    var obj = {
        a: 'world',
        foo: function() {
            console.log(this.a)
        }
    }
    obj.foo()       
    // 浏览器中输出: "world"
    
    var a = 'hello555'
    var obj = {
        a: 'world555',
        b:{
            a:'Ch',
            foo: function() {
                console.log(this.a)
            }
        }
    }
    obj.b.foo()     
    // 浏览器中输出: "Ch"
    

    默认绑定:

    var a = 'hello'
    function foo() {
        var a = 'world'
        console.log(this.a)
        console.log(this)
    }
    foo()             
    // 相当于执行 window.foo()
    // 浏览器中输出: "hello"
    // 浏览器中输出: Window 对象
    
    var a = 'hello'
    var obj = {
        a: 'world55',
        foo: function() {
            console.log(this.a)
        }
    }
    var bar = obj.foo
    bar()              
    // 浏览器中输出: "hello"
    
    var a = 'hello'
    var obj = {
        a: 'world55',
        foo: function() {
            console.log(this.a)
        }
    }
    function func(fn) {
        fn()
    }
    func(obj.foo)              
    // 浏览器中输出: "hello"
    
    

    关于目前文章内容即涉及前端,PHP知识点,如果有兴趣即可关注,很荣幸,能被您发现,真是慧眼识英!也感谢您的关注,在未来的日子里,希望能够一直默默的支持我,我也会努力写出更多优秀的作品。我们一起成长,从零基础学编程,将 Web前端领域、数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯。


    意见反馈:
    若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。


    感谢阅读,原创不易,喜欢就点个赞吧,这是我写作最大的动力。

    欢迎关注达达的简书!

    这是一个有质量,有态度的博客

    博客

    相关文章

      网友评论

          本文标题:你知道多少this,new,bind,call,apply?那我

          本文链接:https://www.haomeiwen.com/subject/scjlictx.html