你不懂JS: this 与对象原型 第二章: this豁然开朗! 在第一章中,我们摒弃了种种对this的误解,并且学习了this是一个完全根据调用点(函数是如何被调用的)而为每次函数调用建立的绑定。 调用点(Call-site) 为了理解this绑定,我们不得不理解调用点:函数在代码中被调用的位置(不是被声明的位置)。我们必须考察调用点来回答这个问题:这个this指向什么? 一般来说寻找调用点就是:“找到一个函数是在哪里被调用的”,但不总是那么简单,比如某些特定的编码模式会使 真正的 调用点变得不那么明确。 考虑 调用栈(call-stack) (使我们到达当前执行位置而被调用的所有方法的堆栈)是十分重要的。我们关心的调用点就位于当前执行中的函数 之前 的调用。 我们来展示一下调用栈和调用点: function baz() { // 调用栈是: `baz` // 我们的调用点是global scope(全局作用域) console.log( "baz" ); bar(); // `bar` // 我们的调用点位于`baz` console.log( "bar" ); foo(); // `bar` -> `foo` // 我们的调用点位于`bar` console.log( "foo" ); } baz(); // 。与使用4种标准的this规则不同的是,箭头函数从封闭它的(function或global)作用域采用this绑定。 我们来展示一下箭头函数的词法作用域: function foo() { // 返回一个arrow function return (a) => { // 这里的`this`是词法上从`foo()`采用 console.log( this.a ); }; } var obj1 = { a: 2 }; var obj2 = { a: 3 }; var bar = foo.call( obj1 ); bar.call( obj2 ); // 2, 不是3! 在foo()中创建的箭头函数在词法上捕获foo()调用时的this,不管它是什么。因为foo()被this绑定到obj1,bar(被返回的箭头函数的一个引用)也将会被this绑定到obj1。一个箭头函数的词法绑定是不能被覆盖的(就连new也不行!)。 最常见的用法是用于回调,比如事件处理器或计时器: function foo() { setTimeout(() => { // 这里的`this`是词法上从`foo()`采用 console.log( this.a ); },100); } var obj = { a: 2 }; foo.call( obj ); // 2 虽然箭头函数提供除了使用bind(..)外,另外一种在函数上来确保this的方式,这看起来很吸引人,但重要的是要注意它们本质是用被广泛理解的词法作用域来禁止了传统的this机制。在ES6之前,我们为此已经有了相当常用的模式,这些模式几乎和ES6的箭头函数的精神没有区别: function foo() { var self = this; // 词法上捕获`this` setTimeout( function(){ console.log( self.a ); }, 100 ); } var obj = { a: 2 }; foo.call( obj ); // 2 虽然对不想用bind(..)的人来说self = this和箭头函数都是看起来不错的“解决方案”,但它们实质上逃避了this而非理解和接受它。 如果你发现你在写this风格的代码,但是大多数或全部时候,你都用词法上的self = this或箭头函数“技巧”抵御this机制,那么也许你应该: 仅使用词法作用域并忘掉虚伪的this风格代码。 完全接受this风格机制,包括在必要的时候使用bind(..),并尝试避开self = this和箭头函数的“词法this”技巧。 一个程序可以有效地同时利用两种风格的代码(词法和this),但是在同一个函数内部,特别是对同种类型的查找,混合这两种机制通常是自找很难维护的代码,而且可能是聪明过了头。 复习 为执行中的函数判定this绑定需要找到这个函数的直接调用点。找到之后,4种规则将会以 这个 优先顺序施用于调用点: 被new调用?使用新构建的对象。 被call或apply(或 bind)调用?使用指定的对象。 被持有调用的环境对象调用?使用那个环境对象。 默认:strict mode下是undefined,否则就是全局对象。 小心偶然或不经意的 默认绑定 规则调用。如果你想“安全”地忽略this绑定,一个像ø = Object.create(null)这样的“DMZ”对象是一个很好的占位值,来保护global对象不受意外的副作用影响。 与这4种绑定规则不同,ES6的箭头方法使用词法作用域来决定this绑定,这意味着它们采用封闭他们的函数调用作为this绑定(无论它是什么)。它们实质上是ES6之前的self = this代码的语法替代品。

this 指向问题的更多相关文章

  1. C语言中 指向函数的指针 简介

    引子:在学习CPrimerPlus的第十四章的14.13节中,遇到了如下三行文字,是有关指向函数的指针的,把我搞晕了. char * fump(); //返回指向char的指针的函数 char (* ...

  2. JS this指向

    正常模式 在正常模式下独立函数的的 this 指向 undefined 或 window. <script type="text/javascript"> functi ...

  3. java多态性,父类引用指向子类对象

    父类引用指向子类对象指的是: 例如父类Animal,子类Cat,Dog.其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类. Animal animal = new C ...

  4. 【javascript 技巧】谈谈setTimeout的作用域以及this的指向问题

    setTimeout的用法详见:http://www.w3school.com.cn/htmldom/met_win_settimeout.asp 是的,setTimeout的常见用法是让某个方法延迟 ...

  5. what's this? 浅谈js中this的指向问题

    刚刚学习js的朋友可能和我一样,看到代码中的this总是一脸懵逼,不知道this到底指向谁.经过一段时间的了解,我想跟大家分享下自己的理解. 何时出现this 函数在调用的时候,会自动获得两个特殊变量 ...

  6. EC笔记,第二部分:10.让=返回指向*this的引用

    Effective C++ 学习笔记 10 让=返回指向*this的引用 Table of Contents 1. 原因 2. 建议:在没有充分理由标新立异前,最好的做法是遵从传统. –by SkyF ...

  7. JavaScript中this指针指向的彻底理解

    this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象 这一点与函数中自由变量Action-varibal不同 var ...

  8. JavaScript中this指向的简单理解

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

  9. 12-返回指针的函数&&指向函数的指针

    前言 接下来我只讲指针的最常见用法,比如这一章的内容----返回指针的函数 与 指向函数的指针   一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的. 返回 ...

  10. 彻底理解js中this的指向,不必硬背。

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

随机推荐

  1. MyBatis的javaType和ofType的区别

    javaType和ofType都是用来指定对象类型,保证了类型安全.反向用select是必须要用ofType.javaType是指POJO类中的属性类型,比如下面的id,text,url,parent ...

  2. redhat7.4 使用centos yum源

    新安装了redhat7.4安装后,登录系统,使用yum update 更新系统.提示: This system is not registered to Red Hat Subscription Ma ...

  3. 无oracle客户端仅用plsql连接远程oracle

    1.在安装ORACLE服务器的机器上搜索下列文件,oci.dllocijdbc10.dllociw32.dllorannzsbb10.dlloraocci10.dlloraociei10.dllsql ...

  4. 四,ESP8266 TCP服务器(基于Lua脚本语言)

    我要赶时间赶紧写完所有的内容....朋友的东西答应的还没做完呢!!!!!!!没想到又来了新的事情,,....... 配置模块作为TCP服务器然后呢咱们连接服务器发指令控制LED亮灭 控制的指令呢咱就配 ...

  5. log下一次坑爹的疏忽

    今天调试一段十几行的代码,也让我是一顿咒骂...就说说是怎么回事哈哈. 是这样的,这个页面foreach了一个个的div块,每个div里有个a标签,这个按钮绑定了个点击事件.事件走了个ajax,根据返 ...

  6. Json.NET序列化后包含类型,保证序列化和反序列化的对象类型相同(转载)

    This sample uses the TypeNameHandlingsetting to include type information when serializing JSON and r ...

  7. Codeforces round 1103

    Div1 534 我可能还太菜了.jpg 果然我只是Div 2 选手 A (这题是Div1吗... 直接构造:竖着放的在第一行和第二行,然后横着放的时候直接放在第三行就行. #include < ...

  8. 20155318 《网络攻防》 Exp7 网络欺诈防范

    20155318 <网络攻防> Exp7 网络欺诈防范 基础问题 通常在什么场景下容易受到DNS spoof攻击 DNS spoof攻击即执行DNS欺骗攻击,通过使用Ettercap来进行 ...

  9. Python+Selenium爬取动态加载页面(2)

    注: 上一篇<Python+Selenium爬取动态加载页面(1)>讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网.数据的获取过程跟人手动获取过程类似,所 ...

  10. [hdu5503]EarthCup[霍尔定理]

    题意 一共 \(n\) 只球队,两两之间会进行一场比赛,赢得一分输不得分,给出每只球队最后的得分,问能否构造每场比赛的输赢情况使得得分成立.多组数据 \(T\le 10,n\le 5\times 10 ...