一周一章前端书·第6周:《你不知道的JavaScript(上)》S02E01
第二部分 - 第1章:关于this
1.1 为什么要用this
this
是一个很特别的关键字,同时也是JavaScript中很复杂的机制,本章讲解this
。我们先看看,不用
this
的代码是怎么样的:
var Me = { name : 'William'}var You = { name : 'Yoki'}//公共方法:返回指定对象的大写namefunction identify(context){ return context.name.toUpperCase(); }//公共方法:用指定对象大写的name,输出hello字符串function speak(context){ var greeting = "Hello,I'm " + identify(context); console.log(greeting); }console.log(identify(You));console.log(identify(Me)); speak(Me); speak(You);
speak()
和identify()
方法不使用this
,则需要显式的传入context
对象,而随着代码越来越复杂,显式传递对象的方式会使得代码愈加混乱。接着我们改写这两个方法,会发现,其实
this
提供了一种更优雅的方式隐式传递对象的引用,这样API也可以设计得更加简洁且复用。
function identify(){ return this.name.toUpperCase(); }function speak(){ var greeting = "Hello,I'm " + identify.call(this); console.log(greeting); }console.log(identify.call(You));console.log(identify.call(Me)); speak(Me); speak(You);
1.2 this的误解
人们很容易把
this
理解成指向函数自身,这从英语的语法上理解是没毛病的,但事实并不是这样的。
function foo(num){ console.log("foo:" + num); this.count++; } foo.count = 0;for(var i=0;i<10;i++){ if(i > 5){ foo(i); } }console.log(foo.count);console.log(count);
控制台输出的是:
foo:6foo:7foo:8foo:90NaN
从上述打印情况来看,
console.log()
语句确实产生了4条输出,证明foo()
方法被调用了4次,但this.count
的指向并不是foo.count
,反而在window
下多出了一个count
,值为NaN
。为了修复上述的结果,当然可以将
foo
方法中的this.count++
改成foo.count++
,但忽略了真正的问题——this
究竟指向谁?下面我们来真正修复这个问题,其实只需要修改
foo()
方法调用的方式即可:
for(var i=0;i<10;i++){ if(i > 5){ //call()方法就是指明哪个对象来调用方法 //之前没使用call()方法时,默认是以window来调用方法,以致于window下会多个count=NaN的变量 foo.call(foo,i); } }console.log(foo.count);
这下输出就正常了,由此可以看出其实
this
真正的含义是:谁调用我,我指向谁。另外需要注意的是,不能通过
this
进行作用域穿越。
function foo(){ var a = 2; bar(); }function bar(){ console.log('a:' + this.a); } foo();
代码试图通过
this
关联foo()
和bar()
作用域,从而让bar()
能访问foo()
作用域中的变量,这是不可能实现的。
1.3 this到底是什么
this
在运行时绑定,而不是编写时,它的指向取决于函数的调用方式。JavaScript当函数被调用时,会创建一个context(上下文/环境)记录,这个记录的内容包含函数在哪里被调用、函数的调用方式、 传入的参数等信息,而
this
就是函数context记录的其中一个属性。
作者:梁同学de自言自语
链接:https://www.jianshu.com/p/ecda46de7adc
共同学习,写下你的评论
评论加载中...
作者其他优质文章