Javascript的this用法

this是Javascript言语的一个关键字。
它代表函数运转时,自动天生的一个内部对象,只能在函数内部运用。比方,
  function test(){
    this.x = 1;
  }
跟着函数运用场所的差别,this的值会发生变化。
有一个总的准绳,那就是this指的是,挪用函数的谁人对象。
下面分四种状况,细致议论this的用法:
状况一:地道的函数挪用

这是函数的最一般用法,属于全局性挪用,因而this就代表全局对象Global。

1)请看下面这段代码,它的运转效果是1。

  

function test(){
    this.x = 1;
    alert(this.x);
  }
  test(); // 1

为了证实this就是全局对象,我对代码做一些转变:

  

var x = 1;
  function test(){
    alert(this.x);
  }
  test(); // 1

运转效果照样1。再变一下:
  

var x = 1;
  function test(){
    this.x = 0;
  }
  test();
alert(x); //0

2)接下来剖析匿名函数下的状况(博客内容外的自增加):

var name="the window";
var object={
    name:"My object",
    getNameFunc:function(){
        return function(){
            return this.name; //没有被直接挪用,此匿名函数的实行环境具有全局性
        };    }
};
alert(object.getNameFunc()());//the window(非严厉形式下)

状况二:作为对象要领的挪用

函数还能够作为某个对象的要领挪用,这时刻this就指这个上级对象。

  

function test(){
    alert(this.x);
  }
  var o = {};
  o.x = 1;
  o.m = test;
  o.m(); // 1

状况三 作为组织函数挪用

所谓组织函数,就是经由过程这个函数天生一个新对象(object)。这时刻,this就指这个新对象。

  

function test(){
    this.x = 1;
  }
  var o = new test();
  alert(o.x); // 1

运转效果为1。为了表明这时刻this不是全局对象,我对代码做一些转变:
 

 

var x = 2;
      function test(){
        this.x = 1;
      }
      var o = new test();
      alert(x); //2

运转效果为2,表明全局变量x的值基础没变。

状况四 apply挪用

apply()是函数对象的一个要领,它的作用是转变函数的挪用对象,它的第一个参数就示意转变后的挪用这个函数的对象。因而,this指的就是这第一个参数。

  

var x = 0;
  function test(){
    alert(this.x);
  }
  var o={};
  o.x = 1;
  o.m = test;
  o.m.apply(); //0

apply()的参数为空时,默许挪用全局对象。因而,这时刻的运转效果为0,证实this指的是全局对象。
如果把末了一行代码修改成
  

o.m.apply(o); //1

运转效果就变成了1,证实了这时刻this代表的是对象o。

                                ----------摘自阮一峰博客

另附笔者看法:

This对象是在运转时基于函数的实行环境绑定的:在全局函数中,this即是window,而当函数作为某个对象的要领挪用时,this即是谁人对象。不过,匿名函数的实行环境具有全局性,因而其this一般指向window。然则因为闭包编写体式格局差别,效果没有那末显著。
别忘了:有一个总的准绳,那就是this指的是,挪用函数的谁人对象。

例1. 匿名函数没有被直接挪用,匿名函数的实行环境具有全局性,this指的是window对象 

var name="the window";
var object={
    name:"My object",
    getNameFunc:function(){
        return function(){
            return this.name;
        };//没有被直接挪用,此匿名函数的实行环境具有全局性
    }
};

alert(object.getNameFunc()());//the window(非严厉形式下)

例2.匿名函数被直接挪用,this指的是挪用它的对象

var name="the window";
var object={
    name:"My object",
    getNameFunc:function(){
            return this.name;
        };//被getNameFunc(也就是object)挪用
    }
};
alert(object.getNameFunc()());//My object(非严厉形式下)

例3.经由过程that绑定实行环境对象(this是关键字,而that不是关键字)

var name="the window";
var object={
    name:"My object",
getNameFunc:function(){
var that=this;//经由过程that绑定了object对象 ;object <--getNameFunc(name)
        return function(){
            return that.name;//建立闭包,返回that.name
        };//object下的name
    }
};
alert(object.getNameFunc()());//My object(非严厉形式下)

模拟块级作用域(私有作用域):
语法以下:



(function(){
//这里是块级作用域
})();

以上代码定义而且马上挪用了一个匿名函数。将函数声明包含在一对圆括号中,示意它实际上是一个函数表达式。而紧随其后的另一对括号会马上挪用这个函数。
类似于:

var someFunction=function(){
//这里是块级及作用域
};
someFunction();

这里定义了一个函数(匿名函数,并把值赋给someFunction)然后马上挪用了它(在函数称号背面增加一对括号)。

下面来看另一种不加括号的状况:

function(){//dosomething}();
例:function (){alert("Hi")}();

这段代码会致使语法毛病,是因为javascript将function关键字看成一个函数声明的最先,而函数声明背面不能跟圆括号。而表达式背面能够跟圆括号,要将函数声明变成表达式,只需向下面那样给它加一对圆括号即可:

(function(){
//这里是块及作用域
})();

如:(function (){alert("Hi")}());

注:

1.result=function(){//dosomething}(); 这个匿名函数后加括号不会报错而且匿名函数会马上实行。
2.result=function(){//dosomething}()与function(){//dosomething}()两个语句完整差别,前者是有赋值的。
3.可行缘由是这里的赋值js实际上把匿名函数看成表达式处理了,表达式背面能够加括号。
而且在function(){//dosomething}()前面加“-“、”!“等运算符还会依据运算划定规矩转变赋给result的值。
4.result=
  1. function(){//dosomething}();
    2.!function(){ // do something }();
    3.~ function() {}();
    4.+ function() {}();
    5.- function() {}()
    道理是语句function(){//dosomething}()都被看成表达式处理了(赋值前盘算表达式的值),就是2、3、4、5例能够自实行,自实行的缘由也是function(){//dosomething}()因为前面的标记被看成表达式处理了

私有作用域实例:

function outputNumbers(count){
    (function(){
        for(var i=0;i<count;i++){
            alert(i);//块级作用域
        }
    })();
    alert(i);//会致使一个毛病,i已被销毁了
}
outputNumbers(5);//0,1,2,3,4
                //抛出毛病

面试题剖析:

1.
var foo = {
    bar: function() { return this.baz; },
    baz: 1
  };
  (function(){
    return typeof arguments[0]();
  })(foo.bar);
答案:"undefined"

在arguments[0]()中实行了一个要领,arguments[0]就是foo.bar要领

注重: foo.bar作为团体传入函数中,然则foo.bar中的this是没有绑定到foo,虽然 foo.bar 通报给了函数,然则真正实行的时刻,函数 bar 的上下文环境是 arguments ,并非 foo。(foo.bar作为团体的通报体式格局解除了foo对bar的挪用作用)

arguemnts[0] 能够理解为 arguments.0(不过写代码就不要如许了,语法会毛病的),所以如许看来,上下文环境是 arguemnts 就没问题了,所以在实行baz的时刻天然this就是window了,window 上没有baz属性,返回的就是undefined, typeof挪用的话就转换成”undefined”了

这里的 this 指的是 arguments,经测试确切云云:

2.

  var foo = {
    bar: function(){ return this.baz; },
    baz: 1
  }
  typeof (f = foo.bar)();
答案:"undefined"
类似于
var foo = { 
  bar: function(){ return this.baz; }, 
  baz: 1 
} 
f = foo.bar; 
typeof f();
把foo.bar存储给f然后挪用,所以this在foo.bar援用的是全局对象,所以就没有baz属性了
换句话说:foo.bar实行的时刻上下文是 foo,然则当 把 foo.bar 赋值给 f 的时刻,f 的上下文环境是 window ,是没有 baz 的,所以是 ”undefined"。

解决方案:应用闭包或许bind()

//函数绑定bind()
function bind(fn,context){//返回闭包
    return function(){
        return fn.apply(context,arguments);//arguments指函数内部的而非bind的
    }
}
//测试
var handler={
    message : "Event Handler",
    handleClick : function(event){
        alert(this.message);
    }
}
//var documentFragment=document.createDocumentFragment();
var text='<button id="button">按钮</button>';
document.body.innerHTML=text;
var btn=document.getElementsByTagName("button")[0];
EventUtil.addHandler(btn,"click",bind(handler.handleClick,handler));
    原文作者:specialCoder
    原文地址: https://segmentfault.com/a/1190000005129170
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞