this、call和apply

作者: Tiny_z | 来源:发表于2017-01-04 22:21 被阅读24次

    this

    JavaScript里面的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

    大致分为下面四种:

    • 作为对象的方法调用
    • 作为普通函数调用
    • 构造器调用
    • Function.prototype.call 或 Function.prototype.apply调用

    1.作为对象的方法调用

      var obj = {
                name : 'zs',
                getName : function(){
                    console.log(this === obj);//true
                    console.log(this.name);//zs
                }
            };
            obj.getName();
    

    2.作为普通函数调用

      var name = 'zs';
            var getName = function(){
                return this.name;
            }
            console.log(getName());// return zs   这里的调用等同于window.getName() 所以this指向window对象
    
      var age = 18;
            var Obj = {
                age : 22,
                getAge : function(){
                    return this.age;
                }
            };
            var getAggetAgee = Obj.getAge;
            console.log(getAge());// return 18 这里也是在全局环境下面调用getAge,所以this也是指向window
    
    //大致来说,this指向当前函数被调用的那个环境。上面两个方法都是在window下面被调用,所以this就指向了window
    

    还有一种情况是,我们有时需要在回调函数里面使用this,但这个时候this往往不是我们预期的那个样子。这个时候,我们可以使用一个变量先保存this

      var obj = {
                name : 'zs',
                getName : function(){
                    return this.name;
                },
                bindEvent : function(){
                    var that = this;
                    document.getElementById('dom').addEventListener('click',function(){
                        console.log(that.getName());
                    })
                }
            }
            obj.bindEvent();//this.getName is not a function  这里的this指向了这个dom元素,所以找不到getName方法
    //可以使用下面这种方法解决
          bindEvent : function(){
                    var that = this;
                    document.getElementById('dom').addEventListener('click',function(){
                        console.log(that.getName());
                    })
                }
    

    3.构造器调用
    JavaScript中没有类,但是可以通过构造器创建对象,同时也提供了new运算符,使的构造器看起来更像一个类。
    在JS中,除了浏览器提供的一些内置函数,大部分JavaScript函数都可以当做构造器使用。构造器的外表和普通函数基本一模一样,区别主要在于被调用的方式。当使用new运算符调用函数时,这个函数就可以理解为构造函数(其实只是构造调用,和普通的函数还是一样的,只是调用的方式不一样),该函数总会返回一个对象,通常情况下,构造器里的this就指向返回的这个函数

      var MyFunc = function(){
                this.name = 'zs';
            }
            var func = new MyFunc();
            console.log(func.name);//return  zs
    
    

    需要注意:如果使用new调用构造函数时,构造函数主动返回了一个object类型的对象,那么此次的运算结果最终会返回这个对象,而不是我们之前期待的this

    var MyFunc = function(){
                this.name = 'zs';
                return {
                    name : 'ls'
                }
            }
    
            var func = new MyFunc();
            console.log(func.name);//return  ls
    

    如果构造器不显示的返回任何数据,或者是返回一个非对象类型的数据,就不会造成上面的问题(例如:上面那里如果是 return '123',是不会造成问题的)

    4.Function.prototype.call和Function.prototype.apply调用
    和普通的函数调用相比,call和apply可以动态的改变传入的this,他们的区别主要在接受的参数格式上
    如果传入的第一个参数为null,函数体内的this会指向默认的宿主对象,浏览器里面是window
    call(this,arg1,arg2...)
    apply(this,[arg1,arg2])

      var obj = {
                name : 'zs',
                getName : function(){
                    return this.name;
                }
            };
    
            var anotherObj = {
                name : 'ls'
            };
    
            console.log(obj.getName());//return zs
            console.log(obj.getName.call(anotherObj));// return ls
    
    Math.max.apply(null,[1,2,3,4]);//4
    

    相关文章

      网友评论

        本文标题:this、call和apply

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