资讯专栏INFORMATION COLUMN

Javascript this 的一些学习总结02【转自cnblogs的JKhuang】

suemi / 3194人阅读

摘要:发生这种情况的条件是当引用类型值的对象恰好为活跃对象。总结本文介绍中的使用,更重要的是帮助我们能更好地理解值在全局函数构造函数以及一些特例的情况中值的变化。然而,由于对于来说没有任何意义,因此会隐式转换为全局对象。

接上一篇Javascript this 的一些学习总结02【转自cnblogs的JKhuang】

引用类型以及this的null值

对于前面提及的情形,还有例外的情况,当调用表达式左侧是引用类型的值,但是this的值却是null,最终变为全局对象(global object)。 发生这种情况的条件是当引用类型值的base对象恰好为活跃对象(activation object)。

当内部子函数在父函数中被调用的时候就会发生这种情况,通过下面的示意代码介绍活跃对象:

// Declares foo function.
function foo() {
  function bar() {
    alert(this); // global
  }
  // The same as AO.bar().  
  bar();
}

由于活跃对象(activation object)总是会返回this值为——null(用伪代码来表示AO.bar()就相当于null.bar()),然后,this的值最终会由null转变为全局对象。

当函数调用包含在with语句的代码块中,并且with对象包含一个函数属性的时候,就会出现例外的情况。with语句会将该对象添加到作用域链的最前面,在活跃对象的之前。 相应地,在引用类型的值(标识符或者属性访问)的情况下,base对象就不再是活跃对象了,而是with语句的对象。另外,值得一提的是,它不仅仅只针对内部函数,全局函数也是如此, 原因就是with对象掩盖了作用域链中更高层的对象(全局对象或者活跃对象):

函数作为构造器被调用时this的值

函数作为构造函数时,我们通过new操作符创建实例对象是,它会调用Foo()函数的内部[[Construct]]方法;在对象创建之后,会调用内部的[[Call]]方法,然后所有Foo()函数中this的值会设置为新创建的对象。

// Declares constructor
function Foo() {
  // The new object.
  alert(this);
  this.x = 10;
}
 
var foo = new Foo();
foo.x = 23;
alert(foo.x); // 23

手动设置函数调用时this的值

Function.prototype原型上定义了两个方法,允许手动指定函数调用时this的值。这两个方法分别是:.apply()和.call()。这两个方法都接受第一个参数作为调用上下文中this的值,而这两个方法的区别是传递的参数,对于.apply()方法来说,第二个参数接受数组类型(或者是类数组的对象,比如arguments), 而.call()方法接受任意多的参数(通过逗号分隔);这两个方法只有第一个参数是必要的——this的值。

通过示例代码介绍call()方法和apply()方法的使用:

var myObject = {};
 
var myFunction = function(param1, param2) {
    
  //setviacall()"this"points to my Object when function is invoked
  this.foo = param1;
  this.bar = param2;
    
  //logs Object{foo = "foo", bar = "bar"}
  console.log(this); 
};
 
// invokes function, set this value to myObject
myFunction.call(myObject, "foo", "bar"); 

// logs Object {foo = "foo", bar = "bar"}
console.log(myObject);

call()方法第一个参数是必要的this值,接着我们可以传递任意多个参数,接着介绍apply()方法的使用。

var myObject = {};
 
var myFunction = function(param1, param2) {
    
  //set via apply(), this points to my Object when function is invoked
  this.foo=param1;
  this.bar=param2;
    
  // logs Object{foo="foo", bar="bar"}  
  console.log(this); 
};
 
// invoke function, set this value
myFunction.apply(myObject, ["foo", "bar"]); 

// logs Object {foo = "foo", bar = "bar"}
console.log(myObject); 

通过与call()方法对比,我们发现apply()方法和call()方法没有太大的区别,只是方法签名不一样。

总结

本文介绍Javascript中this的使用,更重要的是帮助我们能更好地理解this值在全局、函数、构造函数以及一些特例的情况中值的变化。

对于在函数上下文中this的值是函数调用者提供并且由当前调用表达式的形式而定的。如果在调用括号()的左边有引用类型的值,那么this的值就会设置为该引用类型值的base对象。 所有其他情况下(非引用类型),this的值总是null。然而,由于null对于this来说没有任何意义,因此会隐式转换为全局对象。

对于特例情况,我们要记住赋值符、逗号操作符以及||逻辑表达式,会使this丢失原先的引用类型值,变成了函数类型,this的值就变成了全局对象了

参考

http://dmitrysoshnikov.com/ec...英文版

http://blog.goddyzhao.me/post... 译文

https://net.tutsplus.com/tuto...

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

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

相关文章

  • Javascript Context和Scope学习总结02转自cnblogsJKhuang

    摘要:总结本博文通过介绍执行上下文和作用域的异同的使用以及变量对象,让我们加深对语言特性的理解。首先,我们介绍了执行上下文和的的关系,并且执行上下文是具有对象的然后,介绍了作用域使变量在作用域范围内可见,并且作用域是基于函数的。 接上一篇Javascript Context和Scope的学习总结01【转自cnblogs的JKhuang】(可能是segmentfault对单篇文章发布字数有限制...

    Aldous 评论0 收藏0
  • Javascript this 一些学习总结01【转自cnblogsJKhuang

    摘要:函数上下文中的值是函数调用者提供并且由当前调用表达式的形式而定的。然而,由于对于来说没有任何意义,因此会隐式转换为全局对象。这里注意到四个表达式中,只有第一个表达式是指向对象的,而其他三个表达式则执行。 摘要 相信有C++、C#或Java等编程经验的各位,对于this关键字再熟悉不过了。由于Javascript是一种面向对象的编程语言,它和C++、C#或Java一样都包含this关键字...

    Thanatos 评论0 收藏0
  • Javascript Context和Scope学习总结01【转自cnblogsJKhuang

    摘要:正文执行环境也称为环境是中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。简而言之,执行环境是基于对象的,而作用域是基于函数的。 前述 在我们学习Javascript过程中,常常会遇到作用域(Scope)和执行上下文(Context)等概念。其中,执行上下文与this关键字的关系密切。 有面向对象编程经验的各位,对于this关键字再熟悉不过了,因此...

    April 评论0 收藏0
  • 开发中遇到问题总结

    摘要:获取字符串中出现次数最多的字符。去掉字符串中的所有空格中对象数组按对象属性排序 VUE 1、vue——解决You may use special comments to disable some warnings. Use // eslint-disable-next-line to ignore the next line. Use / eslint-disable / to ign...

    wenshi11019 评论0 收藏0
  • 开发中遇到问题总结

    摘要:获取字符串中出现次数最多的字符。去掉字符串中的所有空格中对象数组按对象属性排序 VUE 1、vue——解决You may use special comments to disable some warnings. Use // eslint-disable-next-line to ignore the next line. Use / eslint-disable / to ign...

    Yuqi 评论0 收藏0

发表评论

0条评论

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