Foreword

this 关键字和prototypes

他们是用JS编程的基础。没有他们创建复杂的JS程序是不可能的。

我敢说大量的web developers从没有建立过JS Object,仅仅对待这门语言作为一个事件绑定胶水,在按钮和Ajax请求之间。

我也曾是他们的一员,但是当我了解到如何掌握prototypes并创建JS对象,一个世界的可能性对我打开了。



Chapter 1: this Or That?

this作为一个识别符号关键字自动定义在每个函数的作用域中,但是它究竟涉及什么,甚至困扰着有经验的JS developer。


Why this?

既然很难理解,为什么还使用?它的麻烦大于它的价值吗?

看案例:

  1. function identify() {
  2. return this.name.toUpperCase();
  3. }
  4.  
  5. var me = {
  6. name: "Kyle"
  7. };
  1. var you = {
  2. name: "Reader"
  3. }; 
  1. identify.call( me ); // KYLE
  1. identify.call( you ); // READER

这段代码让identify函数被多次调用。

如果不用this关键字,也可以通过传入一个context对象来实现:

  1. function identify(context) {
  2. return context.name.toUpperCase();
  3. }
  4. identify( you ); // READER

由此可见,this机制提供了更优雅的方式,暗示传入了一个对象,这让API设计更清晰,复用更容易。


Confusions

首先,消除一些错误观念。常常有2个错误的假设:

Itself

假设this是函数自身。

  1. function foo(num) {
  2. console.log( "foo: " + num );
  3.  
  4. // keep track of how many times `foo` is called
  5. this.count++;
  6. }
  7.  
  8. foo.count = 0;
  9.  
  10. var i;
  11.  
  12. for (i=0; i<10; i++) {
  13. if (i > 5) {
  14. foo( i );
  15. }
  16. }
  17. // foo: 6
  18. // foo: 7
  19. // foo: 8
  20. // foo: 9
  21.  
  22. // how many times was `foo` called?
  23. console.log( foo.count ); // 0 -- WTF?
    因为this指向了window对象。this指向的是调用函数的对象。
  1. //在call方法内加上函数对象的identifier名字
  2. for (var i=0; i<10; i++) {
  3. if (i > 5) {
  4. foo.call( foo, i );
  5. }
  6. }
  7.  
  8. // how many times was `foo` called?
  9. console.log( foo.count ); //

除此之外,还有规避this的方法。但都没有直面this到底是什么的问题。

  • 使用foo.count代替this.count.
  • 单独声明一个data对象{ count: 0},用于计数 data.count++

Its Scope

另一个常见的误区是关于this,它涉及了函数的作用域。这里有些诡计:

在某些情况下是对的,但在其他情况下,这么理解是受到误导的!

this关键字,在任何时候,都不涉及一个function的 Lexical scope

  1. function foo() {
  2. var a = 2;
  3. this.bar();
  4. }
  5.  
  6. function bar() {
  7. console.log( this.a );
  8. }
  9.  
  10. foo(); //undefined

写 这段代码的人,试图通过this关键字,把变量a传递给bar函数。以为this是桥梁,能在两个函数的lexical scope之间传递内部变量a。 ❌。没有这个桥梁!!

this不能得到foo函数的Lexical scope!!

this和Lexical scope是不相关的!!!


What's this?

this机制到底是如何工作的?

this和函数调用的方式相关!

当一个函数被invoked,一条记录被创建。这条记录包含信息:

  • 函数从哪里调用(the call-stack)
  • 函数如何被invoked
  • 什么参数被传入。

这条记录的属性之一就是 this 引用。它会在函数的执行期间被使用。

下一章,我们会学习寻找一个函数的call-site(调用点),来决定它的执行如何绑定this关键字

Review

this既不是函数自身的引用也不是函数的lexical作用域的引用!!

this实际是一个在函数被invoked时创建的绑定binding!!!

this引用什么由函数被调用的地点call-site决定!!!

You Don't Know JS: this & Object Prototypes( 第一章 this or That?)的更多相关文章

  1. You Don't Know JS: this & Object Prototypes (第6章 Behavior Delegation)附加的ES6 class未读

    本章深挖原型机制. [[Prototype]]比类更直接和简单! https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%2 ...

  2. You Don't Know JS: this & Object Prototypes( 第5章 Prototypes)

    qu上章提到过[[prototype]] chain, 本章详细分析 ⚠️所有试图模仿类复制的行为,如上章提到的mixins的变种,完全规避了[[Prototype]] chain机制,本章会谈到这方 ...

  3. You Don't Know JS: this & Object Prototypes( 第4章 Mixing "Class" Objects)

    本章移到“Object oriented programming”和"classes". 看‘class orientation‘ 的设计模式: instantiation, in ...

  4. You Don't Know JS: this & Object Prototypes( 第2章 this)

    this is a binding made for each function invocation, based entirely on its call-site (how the functi ...

  5. You Don't Know JS: this & Object Prototypes( 第3章 对象)

    前2章探索了this绑定指向不同的对象需要函数引用的call-site. 但是什么是对象,为什么我们需要指向它们? 本章探索细节. Syntax the rules  that describe ho ...

  6. You Don't Know JS: Async & Performance(第一章, 异步:now & later)

    Chapter 1: Asynchrony: Now & Later 在一门语言中,比如JavaScript, 最重要但仍然常常被误解的编程部分是如何在一个完整的时间周期表示和操作程序行为. ...

  7. JS的Object漫想:从现象到“本质”

    转自:http://zzy603.iteye.com/blog/973649 写的挺好,用于记录,把对象分成概念的Object(var f={})和 类的Object(function F(){}) ...

  8. Javascript中Function,Object,Prototypes,__proto__等概念详解

    http://anykoro.sinaapp.com/2012/01/31/javascript%E4%B8%ADfunctionobjectprototypes__proto__%E7%AD%89% ...

  9. js中Object.defineProperty()和defineProperties()

    在介绍js中Object.defineProperty()和defineProperties()之前,我们了解下js中对象两种属性的类型:数据属性和访问器属性. 数据属性 数据属性包含一个数据的位置, ...

随机推荐

  1. clnt_create: RPC: Program not registered

    原因:[root@nfs nfs]# systemctl start nfs-utils 解决方法:[root@nfs nfs]# systemctl start nfs

  2. Nginx 配置 Jenkins 反向代理

    安装 Nginx 参考之前的一篇文章 Nginx 安装配置 安装 Jenkins 参考之前的一篇文章 Linux 搭建 Jenkins Nginx 配置 Jenkins 的反向代理 # /etc/ng ...

  3. HIHOcoder 1403 后缀数组一·重复旋律

    思路 后缀数组的板子题,注意后缀数组的rank[]数组是通过位置找到对应排名的,sa[]是通过排名找到位置的,height[i]记录的是sa[i]和sa[i+1]之间的lcp 不要写错了就行了 代码 ...

  4. Java 大数任意进制转换

    import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner cin = ...

  5. InnoDB锁笔记

    InnoDB主要使用行级锁(row lock),其行锁是通过在索引项上加锁而实现的,如果MySQL的执行计划没有用到索引,那么行锁也就无意义了 InnoDB的行锁是通过给索引上的索引(聚集,非聚集)添 ...

  6. C盘清理

    魔方清理大师 “清理大师”->清理界面 一键清理=>开始扫描=>立刻清理 注册表清理=>开始扫描=>立刻清理 深度清理=>开始扫描=>立刻清理 C:\User ...

  7. Ubuntu16.04更新记

    大概一周前因为不可抗因素,我再次安装了Ubuntu16.04LTS 对于之前发誓不想再用Ubuntu的我,我只想说一句:真香 写一点我现在Ubuntu的配置,方面自己以后查看,也方便如果有相同需求的人 ...

  8. Using keytool to import keystore

    open command line and locate to the location of  keytool.exe. import cert to keystore command: keyto ...

  9. R----ggplot2包介绍学习--转载

    https://www.cnblogs.com/nxld/p/6059603.html 分析数据要做的第一件事情,就是观察它.对于每个变量,哪些值是最常见的?值域是大是小?是否有异常观测? ggplo ...

  10. 【RFT】【环境配置】Mac

    参考地址:http://blog.csdn.net/u010044052/article/details/70858015?utm_source=itdadao&utm_medium=refe ...