资讯专栏INFORMATION COLUMN

Javascript的this用法

ad6623 / 2981人阅读

摘要:不过,匿名函数的执行环境具有全局性,因此其通常指向。可行原因是这里的赋值实际上把匿名函数当作表达式处理了,表达式后面可以加括号。

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=

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

面试题解析:

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="";
document.body.innerHTML=text;
var btn=document.getElementsByTagName("button")[0];
EventUtil.addHandler(btn,"click",bind(handler.handleClick,handler));

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79463.html

相关文章

  • 快速理解JavaScriptthis用法与陷阱

    摘要:赫敏第三行的是在最外层执行,也就是在全局对象下。而在对象下声明了属性,就相当于罗恩,输出的当然就是罗恩。之所以写这篇文章,是为了我下一篇文章做铺垫快速理解中和的用法敬请期待 this是 JS 这门语言的魅力之一——灵活方便又难以捉摸,即使是有经验的程序员,如果不仔细也有可能搞错,关于this的用法也成为许多公司的经典面试题。 如果你写过 Java ,你可能接触过this——一般指向当前...

    Kylin_Mountain 评论0 收藏0
  • 关于javascriptbind、call、apply等函数用法

    摘要:其实它们都很简单,但是在处理一些与相关的函数的时候,用来改变函数中的指向,却是必不可少的工具,所以必须掌握好它们的用法。 关于javascript中的bind、call、apply等函数的用法 我GitHub上的菜鸟仓库地址: 点击跳转查看其他相关文章 文章在我的博客上的地址: 点击跳转         前面的文章已经说到this的指向了,那么这篇文章就要说一说和this相关的三个...

    lordharrd 评论0 收藏0
  • JavaScript 函数作用域、执行环境(this)、call、apply、bind 用法

    摘要:什么是函数的作用域函数作用域在中,作用域为可访问变量,对象,函数的集合。函数作用域作用域在函数内修改。与函数又有什么关系呢对象是在运行时基于函数的执行环境绑定的。 什么是函数的作用域 函数作用域:在 JavaScript 中,作用域为可访问变量,对象,函数的集合。JavaScript 函数作用域: 作用域在函数内修改。 this 与函数又有什么关系呢? this对象是在运行时基于函数的...

    1fe1se 评论0 收藏0
  • JavaScript prototype原型用法

    摘要:使用原型属性属性允许您向对象构造函数添加新属性属性还允许您向对象构造函数添加新方法更好的原型对象的教程 JavaScript对象原型所有JavaScript对象都从原型继承属性和方法。 js JavaScript 对象 function Person(first, last, age, eye) { this.firstName = fi...

    siberiawolf 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<