zoukankan      html  css  js  c++  java
  • 函数调用的四种方式 和 相关的 --- this指向

    • this:表示被调用函数的上下文对象。
    • arguments:表示函数调用过程中传递的所有参数。
    • 这两个参数都是隐式的函数参数。会静默传递给函数,并且和函数体内显式声明的参数一样可正常访问。
    • arguments有length属性,可以通过下标方式访问每个元素,但是它不是数组,是类数组。

    函数调用的四种方式:区别主要在于this值得不同。 (对于作为方法调用而言,this为方法所在的对象//   对于顶级函数this 则为window或undefined//   对于构造函数而言this为新创建的实例)

    • 作为一个函数(function)---test(),直接被调用  
      function test(){
        //函数体          -------函数定义作为函数被调用
      }
      test();
      
      var test=function(){  };
      test();                     --------------函数表达式作为函数调用

       当以上面的方式调用,函数的上下文(this)有两种可能性:在非严格模式下,会是全局上下文(window对象);在严格模式下,是undefined。

      1     function test(){
      2         console.log(this);   //window
      3     }
      4     test();
    • 作为一个方法(method)---ml.test()关联在一个对象上。
      var obj1={
              getMythis:test
          };
      var obj2={
              getMythis:test
          };
      function test() { 
      console.log(this);
       } 
      obj1.getMythis(); //返回上下文 对象obj1
      obj2.getMythis(); //返回上下文 对象obj2

       通过this在任何方法中的引用该方法的宿主对象。调用同样的方法 但由于对象不同 返回的上下文也不同。

    • 作为一个构造函数---new test(),实例化一个新对象。

          通过构造函数的方式调用时,需要在函数调用之前加上关键字new。上例中函数test 的构造函数调用方式为:

    var obj=new test();

     通过new 关键字调用时会创建一个空的对象实例,并将其作为函数上下文(this参数)传递给函数。在构造函数中创建的属性和方法会在实例化后赋值给该对象。

     调用构造函数时会发生如下操作:

    1. 创建一个新的空对象。
    2. 该对象作为this参数传递给构造函数,从而构成构造函数的函数上下文。
    3. 新构造的对象作为new运算符的返回值。 

         构造函数的目的:创建一个新对象,并进行初始化设置,然后将其作为构造的返回值。将返回结果存储在变量中,后续通过这些变量引用新创建的对象。

         即:初始化新创建的对象。

    1    var puppet={
    2        rule:false
    3    };
    4    function Emperor(){
    5        this.rules=true;
    6        return puppet;
    7    }
    8    var emperor=new Emperor();
    9    console.log(emperor===puppet);   //true 

       打印结果 emperor为对象,包含属性rules,而不是Emperor函数调用后的返回值。

    总结:

    1. 如果构造函数返回一个对象,则该对象将作为整个表达式的值返回,而传入构造函数的this将会被废弃。
    2. 但是,如果构造函数返回是非对象类型,则忽略返回值,返回新创建的对象。
    • 通过函数的apply和call方法                 ---sk.call(test)  /   sk.apply(test); 用法区别是:如何传参。
     1     function Button(){
     2         this.clicked=false;
     3         this.click=function(){
     4             this.clicked=true;
     5             console.log(button.id);
     6         }
     7     }
     8     var button=new Button();
     9     var elem=document.getElementById("test");
    10     elem.addEventListener("click",button.click);  //undefined

     原因:  click函数的上下文并非执行button对象。上下文为按钮即:button元素,并非button对象。

    更正

     1     function Button(){
     2         this.clicked=false;
     3         this.click=function(){
     4             this.clicked=true;
     5             console.log(button.id);
     6         }
     7     }
     8     var button=new Button();
     9     var elem=document.getElementById("test");
     10    elem.addEventListener("click",button.click.bind(button));  
           //test

    call  和apply  实际使用方法:

        function Sum(){
            var result=0;
            for(var i=0;i<arguments.length;i++){
                result+=arguments[i];
            }
            return this.result=result;
        }
        var test1={};
        var test2={};
        Sum.apply(test1,[1,2,3,4]);
        Sum.call(test2,5,6,7,8);
        console.log(test1.result);  //10
        console.log(test2.result);  //26

    其中Sum作为test1和test2对象的方法被调用,且函数上下文指向这些对象。实质为Sum函数的正常调用,只不过函数上下文为括号内传入的对象,手动设置函数上下文

    • 解决函数上下文的另外两种选择:箭头函数和bind方法。

    箭头函数的this不会隐式传入,从定义时的函数继承上下文。如下例子所示:

    1  var button= {
    2      clicked: false,
    3      click:()=>{
    4      this.clicked = true;
    5      console.log(button.clicked);
    6    }
    7  }
    8 button.click(); //false
    9 console.log(window.clicked); //true

    因为click箭头函数是作为对象字面量的属性定义的,对象字面量是在全局代码中定义的,因此,箭头函数内部this与全局对象的this值相同。

    • bind方法:创建并返回一个新函数,并绑定在传入的特定的对象上。函数体与原函数一致。

     bind,apply,call异同:

    共同点:都是改变this对象的指向问题。

    区别:

    1、bind返回值是新的函数,必须调用才能执行,后两者均为立即执行。

    2、apply和call的传参方式不同,apply为传入数组,而call为一个个传入。bind和call传参类型相同。

  • 相关阅读:
    论文笔记之:Playing for Data: Ground Truth from Computer Games
    【计算机视觉领域】常用的 feature 提取方法,feature 提取工具包
    论文阅读之:Is Faster R-CNN Doing Well for Pedestrian Detection?
    论文笔记之:Generative Adversarial Nets
    如果读取图像的图像出现坏图,无法读取的怎么办?怎么自动跳过坏的图像,而读取下一张?
    (转)A Beginner's Guide To Understanding Convolutional Neural Networks
    (转) Written Memories: Understanding, Deriving and Extending the LSTM
    如果将彩色图像和灰度图像一起放进 CNN 中去,会是什么结果?
    3D CNN for Video Processing
    nodejs(四) --- cluster模块详解
  • 原文地址:https://www.cnblogs.com/alaner/p/9539312.html
Copyright © 2011-2022 走看看