zoukankan      html  css  js  c++  java
  • JavaScript中this关键词的四种指向

    JavaScript中this关键词的四种指向
    我曾经听一位喜剧演员说过:
    “我从未在这里,因为我不清楚这里是哪里,是除了那里之外的地方吗?”
    这句话或多或少地暗喻了在js开发中开发者对于this关键字的使用误区。This指代的是什么?它和日常英语口语中的this是一个意思吗?
    随着近些年js编程不断地复杂化,功能多样化,对于一个程序结构的内部指引、引用也逐渐变多起来
    下面让我们一起来看这一段代码:
    Game.prototype.restart = function () {

    this.clearLocalStorage();
    this.timer = setTimeout(function(){

    this.clearBoard();

    }, 0);
    };
    运行上面的代码将会出现如下错误:
    Uncaught TypeError: undefined is not a function
    这是为什么?this的调用和它所在的环境密切相关。之所以会出现上面的错误,是因为当你在调用 setTimeout()函数的时候, 你实际调用的是window.setTimeout(). 因此,在 setTimeout() 定义的函数其实是在window背景下定义的,而window中并没有 clearBoard() 这个函数方法。
    下面提供两种解决方案。第一种比较简单直接的方法便是,把this存储到一个变量当中,这样他就可以在不同的环境背景中被继承下来:
    Game.prototype.restart = function () {

    this.clearLocalStorage();
    var self = this;
    this.timer = setTimeout(function(){

    self.clearBoard();

    }, 0);

    };
    第二种方法便是用bind()的方法,不过这个相比上一种要复杂一些,对于不熟悉bind()的同学可以在微软官方查看它的使用方法:
    Game.prototype.restart = function () {

    this.clearLocalStorage();
    this.timer = setTimeout(this.reset.bind(this), 0);

    };
    Game.prototype.reset = function(){

    this.clearBoard();

    };
    上面的例子中,两个this均指代的是Game.prototype。

    this并不指向当前对象,这是理解this的关键所在,this的指向取决于你是采用何种方式调用this所在的这个函数的,其实也只有四种调用模式,搞清楚了就以不变应万变。在javascript中一共有四种调用模式:方法调用模式,函数调用模式,构造器调用模式,apply/call调用模式。这些模式在如何初始化关键参数this上存在差异。

    1 方法调用模式(对象名.方法名(),或对象名[“方法名”]())

    当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。如果一个调用表达式包含一个属性存取表达式(即一个.点表达式或者[subscript]下标表达式),那么它被当做一个方法来调用

    var myObject = {
    
    value :0,
    
    increment:function (inc){
    
    this.value += typeof inc ==='number' ? inc:1;
    
    }
    
    };
    
    myObject.increment();
    
    document.writeln(myObject.value);  //1
    
    myObject.increment(2);
    
    document.writeln(myObject.value);  //3
    

      

    方法可以使用this去访问对象,所以它能从对象中取得或修改该对象。this到对象的绑定发生在调用的时候。这个“超级”迟绑定( very late binding)使得函数可以对this高度复用。通过this可取得它们所属对象的上下文的方法称为公共方法。

    2 .函数调用模式

    当一个函数并非一个对象的属性是,那么它被当做一个函数来调用:var sum = add(3,4); //sum的值为7,当函数以此模式调用时,this被绑定到全局对象window上。这是语言设计上的一个错误,倘若语言设计正确,当内部函数被调用时,this应该仍然绑定到外部函数的this变量。这个设计错误错误的后果是方法不能利用内部函数来帮助它工作,因为内部函数的this被绑定了错误的值,所以不能共享该方法对对象的访问权。幸运的是,可以利用闭包特性保存this到一个自定义变量:如果该方法定义一个变量并给他赋值为this,那么内部函数就可以通过那个变量访问到this。

    //给myObject增加一个double方法
    
    myObject.double = function(){
    
     var self = this; //解决方案
    
     var doubleFn = function(){
    
        self.value = self.value*2;
    
     };
    
     doubleFn ();//以函数的形式调用
    
    };
    
    //以方法的形式调用double
    
    myObject.double();
    
    document.writeln(myObject.getValue()); //6

    3 . 构造器函数调用模式

    使用new 方式调用一个函数,那么这个函数被称之为构造器函数,这个构造器函数会创建出来一个新生的对象,这个新生对象的constructor指向这个构造器函数。

    Function myFun(){
    
             this.color=”red”;
    
    }
    
    var obj=new myFun();
    
    console.log(obj.color); //red;
    

    4  .apply/call 调用方式

    apply调用方式最为强大,可以指定this为任意对象,call的功能和apply一样,只是接收的参数有区别。

    var user={
    
    name:'windy',
    
    say:'hello,world'
    
    }
    
    var obj={
    
            test:function(){
    
                       alert(this.name+':'+this.say);
    
    }
    
    }
    
    obj.test.apply(user);
    

    参考网址:http://www.cnblogs.com/windyfancy/p/5167209.html

    参考网址:http://www.cnblogs.com/windyfancy/p/5167266.html

    爱前端,爱代码
  • 相关阅读:
    [模板] 循环数组的最大子段和
    [最短路][几何][牛客] [国庆集训派对1]-L-New Game
    [洛谷] P1866 编号
    1115 Counting Nodes in a BST (30 分)
    1106 Lowest Price in Supply Chain (25 分)
    1094 The Largest Generation (25 分)
    1090 Highest Price in Supply Chain (25 分)
    树的遍历
    1086 Tree Traversals Again (25 分)
    1079 Total Sales of Supply Chain (25 分 树
  • 原文地址:https://www.cnblogs.com/jtr122624520/p/5918584.html
Copyright © 2011-2022 走看看