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

爱前端,爱代码
原文地址:https://www.cnblogs.com/jtr122624520/p/5918584.html