You Don't Know JS: this & Object Prototypes( 第一章 this or That?)

Posted Mr-chen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了You Don't Know JS: this & Object Prototypes( 第一章 this or That?)相关的知识,希望对你有一定的参考价值。

Foreword

 

this 关键字和prototypes

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

 

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

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


 

 


 

Chapter 1: this Or That?

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


 

Why this?

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

看案例:

function identify() {
    return this.name.toUpperCase();
}

var me = {
    name: "Kyle"
};

var you = {
	name: "Reader"
}; 
identify.call( me ); // KYLE
identify.call( you ); // READER

 

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

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

function identify(context) {
    return context.name.toUpperCase();
}
identify( you ); // READER

 

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


 

 

Confusions

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

Itself

假设this是函数自身。

function foo(num) {
    console.log( "foo: " + num );

    // keep track of how many times `foo` is called
    this.count++;
}

foo.count = 0;

var i;

for (i=0; i<10; i++) {
    if (i > 5) {
        foo( i );
    }
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9

// how many times was `foo` called?
console.log( foo.count ); // 0 -- WTF?
因为this指向了window对象。this指向的是调用函数的对象。

 

//在call方法内加上函数对象的identifier名字
for (var i=0; i<10; i++) {
    if (i > 5) {
        foo.call( foo, i );
    }
}

// how many times was `foo` called?
console.log( foo.count ); // 4

 

 

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

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

 

Its Scope

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

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

 

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

function foo() {
    var a = 2;
    this.bar();
}

function bar() {
    console.log( this.a );
}

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?)的主要内容,如果未能解决你的问题,请参考以下文章

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

You Don't Know JS: Scope & Closures (第4章: Hoisting)

You Don't Know JS: Scope & Closures (附加:Lexical/dynamic作用域)

You Don't Know JS: Scope & Closures (第3章: 函数 vs 块作用域)

You Don't Know JS: this & Object Prototypes( 第一章 this or That?)

(未完成👃)You Don't Know JS: Scope & Closures (第5章: Scope & Closures)