摘要:不过匿名函数的执行环境具有全局性,因此其对象通常指向。在闭包中使用对象可能会导致一些问题。这个对象还包含一个方法它返回一个匿名函数,而匿名函数又返回,这个匿名函数就是闭包。伪代码过程在定义匿名函数之前,把对象赋值给了一个名叫的变量。
this对象
前言:最近在细读Javascript高级程序设计,对于我而言,中文版,书中很多地方翻译的差强人意,所以用自己所理解的,尝试解读下。如有纰漏或错误,会非常感谢您的指出。文中绝大部分内容引用自《JavaScript高级程序设计第三版》。
this对象是在运行时基于函数的执行环境绑定:
在全局环境中, this等于window,而当函数被作为某个对象的方法调用时,this就指向了那个对象。
不过匿名函数的执行环境具有全局性,因此其this对象通常指向window。
在闭包中使用this对象可能会导致一些问题。
有时候由于编写闭包的方式不同,这一点可能不会那么明显。
// 在全局环境中,this等于window function thisBoundForWindow(){ console.log(this); console.log(this.name); } thisBoundForWindow(); // Window var o = new Object(); o.name = "Shaw"; //当函数被作为某个对象的方法调用时,this就指向了那个对象。 thisBoundForWindow.apply(o); // {name: "Shaw"}; "Shaw" ;
//在闭包中使用this对象可能会导致一些问题。 //有时候由于编写闭包的方式不同,这一点可能不会那么明显。 var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { return function() { console.log(this.name); } } } object.getNameFunc()(); // "The Window" /* object.getNameFunc return=> function() { return function() { console.log(this.name); } } => ()调用,还是在全局环境下调用的,所以this.name = window.name => "The Window" */
以上代码先创建了一个全局变量name,又创建了一个包含name属性的对象。
这个对象还包含一个方法——getNameFunc(), 它返回一个匿名函数,而匿名函数又返回this.name,这个匿名函数就是闭包。
再来回顾一下“闭包”的定义:
有权访问另外一个作用域中的变量的函数就是闭包。
由于getNameFunc()返回一个函数,因此调用object.getNameFunc()()就会调用它返回的函数,结果就是控制台打印出一个字符窜。
然而,这个例子返回的字符窜是"The Window",即全局name变量的值。
那么,如何把this指向例子中的object呢?
把外部作用域的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了。(注意,这种手法,在使用回调函数的时候也经常用到)。
var name = "The Window"; var object = { name: "My Object", getNameFunc: function(){ var that = this; return function() { console.log(that.name); } } } object.getNameFunc()(); // "My Object" /* // 伪代码过程 object.getNameFunc execute => this = object = that =>function() {console.log(that.name);} => () => that.name = object.name => "My Object" */
在定义匿名函数之前,把this对象赋值给了一个名叫that的变量。
而在定义了闭包之后,闭包也可以访问这个变量,因为它是我们在包含函数中特意声明的一个变量。
即使在函数返回之后,that也仍然引用着object, 所以调用Object.getNameFunc()就返回了"My Object"。
在几种特殊情况下,this的值可能会意外地改变。比如,下面的代码时修改前面例子的结果。
var name = "The Window"; var object = { name: "My Object", getName: function() { console.log(this.name); } }; object.getName(); // "My Object" (object.getName)(); // "My Object" (object.getName = object.getName)(); // "The Window"
第一行代码跟平常一样调用了object.getName(),返回时"My Object",因为this.name就是object.name。
第二行代码在调用这个方法前给它加上了括号,虽然加上括号之后,就好像是在引用一个函数,但this的值得到了维持,因为object.getName和(object.getName)的定义是相同的。
第三行代码先执行了一条赋值语句,然后再调用赋值后的结果。因为这个赋值表达式是函数本身,所以this的值得不到维持,结果就返回了"The Window"。
//第三个例子伪代码 //理解此段代码,首先要明确一个知识点:赋值语句是有返回值的,返回值就是所赋的值(也就是‘=’右边的值)。 (object.getName = object.getName)(); // "The Window" (object.getName = function(){ console.log(this.name)})(); (function(){console.log(this.name)})(); //所以this指向window
当然,我们不太可能会像第二行和第三行代码一样调用这个方法。暂时理解不了也没事,这个例子有助于说明即使是语法的细微变化,都有可能意外地改变this值。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/98774.html
摘要:另外,的绑定和函数声明的位置没有任何关系,之取决于函数的调用方式。请看下面代码这样,我们就可以在调用的时候强制把它的绑定到上绑定在传统的面向类语言中,使用初始化类时会调用类中的构造函数。 关于this 上一章我们讲了关于作用域和闭包的相关知识,现在开始新一轮的学习,那就是JavaScript中最复杂的机制之一---this关键字。它是一个很特别的关键字,被自动定义在所有函数的作用域中。...
摘要:理解的函数基础要搞好深入浅出原型使用原型模型,虽然这经常被当作缺点提及,但是只要善于运用,其实基于原型的继承模型比传统的类继承还要强大。中文指南基本操作指南二继续熟悉的几对方法,包括,,。商业转载请联系作者获得授权,非商业转载请注明出处。 怎样使用 this 因为本人属于伪前端,因此文中只看懂了 8 成左右,希望能够给大家带来帮助....(据说是阿里的前端妹子写的) this 的值到底...
摘要:模拟实现操作符构造函数返回结果创建一个空对象取传入的第一个参数,即构造函数,并删除第一个参数。二处理返回值构造函数也是函数,有不同类型返回值。有时候构造函数会返回指定的对象内容,所以要对这部分进行处理。 本文共 1230 字,读完只需 5 分钟 写在前面 最近工作太忙,快接近两周没更新博客,总感觉有一些事情等着自己去做,虽然工作内容对自己提升挺大,但我总觉得,一直埋着头走路,偶尔也...
摘要:之前总结了的一些常见绑定情况前端工程师手册之的笔记,但是还有一些没有说到,今天继续学习一下。参考资料箭头函数你不知道的上卷 之前总结了this的一些常见绑定情况(【前端工程师手册】JavaScript之this的笔记),但是还有一些没有说到,今天继续学习一下。 es6箭头函数 先说结论:箭头函数没有自己的this,它是根据外层(函数或者全局,后面会说到箭头函数作为某个对象的方法时的情况...
摘要:第四点也要着重讲下,记住构造函数被操作,要让正常作用最好不能在构造函数里 4) this、new、call和apply的相关问题 讲解this指针的原理是个很复杂的问题,如果我们从javascript里this的实现机制来说明this,很多朋友可能会越来越糊涂,因此本篇打算换一个思路从应用的角度来讲解this指针,从这个角度理解this指针更加有现实意义。 下面我们看看在ja...
阅读 3807·2023-04-25 19:07
阅读 3553·2021-11-22 12:02
阅读 3138·2021-10-12 10:11
阅读 3907·2021-09-03 10:49
阅读 2891·2019-08-30 13:21
阅读 2997·2019-08-30 11:14
阅读 2089·2019-08-29 15:40
阅读 2872·2019-08-28 18:29