zoukankan      html  css  js  c++  java
  • javascript中的this、 call() 和 apply()

    1:this

       javascript中的this总是指向一个对象的,至于是指向哪一个对象,是运行时基于函数的执行环境的动态绑定的,尔非函数被声明时的环境;

      this的指向可以分为四类:

    •   作为对象的方法调用
    •   作为普通函数调用
    •   构造器调用
    •   Function.prototype.call()和Function.prototype.apply()
       1.1:作为对象的方法调用:

       当函数作为对象的方法被调用时,this指向该对象

    //obj对象
      var obj={
       name:name;
       getName:function(){
       concole.log(this===obj);  //输出true
      console.log(this.name);     //输出name
      }
    };
    obj.getName();
       1.2作为普通函数调用:

         当函数不作为对象的属性被调用时,也就是以普通函数方式,this指向全局对象,在浏览器的javascript中,全局对象指的是winows对象

    window.name=‘globalName’;   //声明全局对象name的属性
    
    var getName=function(){
       return this.name;
    }
    
    console.log(getName());        //输出globalName;
    
    
    
    window.name='globalName';   //声明全局对象name的属性
    
    var obj={
        name:'myObjName',
        getName:function(){
        return this.name;
    },
    }
    
    var myobj=obj.getName;
    console.log(myobj());             //输出globalName;
     1.3构造器调用:

                 javascript没有类,可以从构造器中创建对象,也提供了new运算符调用构造器。大部分javascript函数都可以当做构造器使用,构造器的外表和普通函数并没有什么两样,区别就是被调用的方式,即使用new运算符创建对象时,就是将函数当做构造器调用。当用new运算符调用函数时,该函数总会返回一个对象,此时,构造器里的this指向返回的这个对象。

    var myClass=function(){
       this.name='classname';
    };
    
    var obj=new myClass();
    console.log(obj.name);    //输出classname

                 但,如果构造器显式地返回了一个object类型的对象,那么此函数将返回这个object类型的对象,而不是函数本身所定义的对象,例如:

    var myClass=function(){
     
     this.name='classname';
       return{
        name:'lihe'
        };
    };
    
    var obj=new myClass();
    console.log(obj.name);        //输出lihe

                而,如果构造器不显式地返回任何数据,或返回一个非对象类型的数据,就不会造成上述情形。

    var myClass=function(){
    
    this.name='classname';
    return 'lihe';
    };
    
    var obj=new myClass();
    console.log(obj.name);      //输出classname

    1.4.Function.prototype.call 或 Function.prototype.apply调用

               跟普通函数调用相比,用 Function.prototype.call 或 Function.prototype.apply 可以动态地改变传入函数的this

    var A={
    name:'classnameA',
    getName:function(){
       return this.name;
    },
    };
    
    
    var B={
    name:'classnameB',
    };
    
    console.log(A.getName());                //classnameA
    console.log(A.getName.call(B));     //classnameB 

           丢失的this:

                当this的指向,与我们期待的不同时,就会出现undefined情况

    var  obj={
      name:'classname',
      getName:function(){
       return this.name
    },
    };
    
    //作为对象的方法引用,指向obj对象
    console.log(obj.getName());   //输出classname
    
    //作为普通函数调用,指向全局对象window,name属性还没定义
    var getName2=obj.getName;
    console.log(obj.getName2);      //输出undefined

       2   call和apply


    Function原型的两个方法Function.prototype.call()  Function.prototype.apply()

    call和apply区别:作用一样,传入参数形式不同

    apply接受两个参数,第一个参数制定了函数体内this对象的指向,第二个函数为一个带下标的集合,这个集合可以是数组,也可以是类数组。apply方法把这个集合中的元素作为参数传递给被调用的函数。

    var func = function(a, b, c){
      console.log([a, b, c]);  
    };
    
    func.apply(null, [1, 2, 3]);

    call传入的参数数量不固定,第一个参数也是代表了函数体内的this指向,从第二个参数开始往后,每个参数依次被传入函数:

    var func = function(a, b, c){
      console.log([a, b, c]); 
    };
    
    func.call(null, 1, 2, 3);

    当使用call或apply的时候,如果我们传入的第一个参数为null,函数体内的this会指向默认的宿主对象,在浏览器中则是window:

    var func = function(a, b, c){
      console.log(this);
    };
    
    func.apply(null, [1, 2, 3]);  //输出:window对象
    func.call(null, 1, 2, 3);        //输出:window对象

    3.call()  和apply()用途

    • 改变this指向

    • Function.prototype.bind

    • 借用其他对象的方法

    3.1改变this指向:改变函数内部this的指向

    var A = {
      name: 'nameA',
    };
    
    var B = {
      name: 'nameB',
    };
    
    window.name = 'nameWindow';
    
    var getName = function(){
      console.log(this.name);
    };
    
    getName();             // 以普通函数调用,指向了window对象,输出nameWindow
    getName.call(A);      // 改变了this的指向,指向了传入的对象,输出:nameA
    getName.call(B);      // 改变了this的指向,指向了传入的对象,输出:nameB

    3.2Function.prototype.bind

    大部分高级浏览器都实现了内置的Function.prototype.bind,用来指定函数内部的this指向。若没有原生的Function.prototype.bind实现,可以通过模拟一个:

    Function.prototype.bind = function(context){
      var self = this;  // 保存原函数
      return function(){  // 返回一个新的函数
          return self.apply(context, arguments);  // 执行新函数的时候,会把之前传入的context当作新函数体内的this
      }
    };
    
    var obj = {
     name: "objName"
    };
    
    var func = function(){
      console.log(this.name);  
    }.bind(obj);
    
    func();                     // 输出:objName

    3.3借用其他对象的方法

    •     类数组对象的操作

    想把arguments转成真正的数组的时候,可以借用Array.prototype.slice方法;

    想往arguments中添加一个新的元素,可以借用Array.prototype.push:

    想截去arguments列表中的头一个元素时,可以借用Array.prototype.shift方法。

    (function(){
      Array.prototype.push.call(arguments, 3);
      console.log(arguments); // 输出:[1,2,3]
    })(1, 2);
    •    借用构造函数,可以实现类似继承
    var A = function(name){
     this.name = name;
    };
    
    var B = function(){  // 借用A的构造函数
      A.apply(this, arguments); 
    };
    
    B.prototype.getName = function(){
      return this.name;
    };
    
    var b = new B('baby');
    console.log(b.getName());  // 输出:baby
  • 相关阅读:
    【论文阅读】Transformer及其在计算机视觉领域上的应用
    【学习笔记】asyncio的使用
    【论文阅读】Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization
    【论文阅读】Bag of Tricks for Image Classification with Convolutional Neural Networks
    【论文阅读】Bag of Tricks and A Strong Baseline for Deep Person Re-identification
    【论文阅读】主动学习 (Active Learning)
    可能有点用的东西
    .vimrc
    莫比乌斯反演 学习笔记
    对拍
  • 原文地址:https://www.cnblogs.com/lulu-front/p/4946436.html
Copyright © 2011-2022 走看看