zoukankan      html  css  js  c++  java
  • 你知道多少this,new,bind,call,apply?那我告诉你

    那么什么是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 前端相关的技术文章、工具资源、精选课程、热点资讯。


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


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

    欢迎关注达达的简书!

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

    博客

  • 相关阅读:
    布局重用 include merge ViewStub
    AS 常用插件 MD
    AS 2.0新功能 Instant Run
    AS .ignore插件 忽略文件
    AS Gradle构建工具与Android plugin插件【大全】
    如何开通www国际域名个人网站
    倒计时实现方案总结 Timer Handler
    AS 进行单元测试
    RxJava 设计理念 观察者模式 Observable lambdas MD
    retrofit okhttp RxJava bk Gson Lambda 综合示例【配置】
  • 原文地址:https://www.cnblogs.com/dashucoding/p/11854532.html
Copyright © 2011-2022 走看看