前言
this关键字是JavaScript中最复杂的机制之一,本文将初步了解this机制以及两种常见对this的误解。(注意:针对初学者的,学过得码工可以回顾一下)
在了解this之前,是否了解这些js知识点 (文章进行比较)
-词法作用域或者是词法标识符
提示:以下是本篇文章正文内容,下面案例可供参考
一、this是什么?为什么要使用this?
“this“是沟通过程中极为重要的代词,在英文本身翻译为这个;
在我们使用this这个关键词时,想想,为什么要使用this关键词呢?
下面代码会进行解释为什么要使用this
function identify(){
return this.name.toUpperCase()
}
function speak(){
var greeting = 'Hello I am '+ identify.call(this)
console.log(greeting)
}
var me = {
name: "luck"
}
var your = {
name: 'lucy'
}
console.log(identify.call(me))
console.log(identify.call(your))
speak.call(me)
speak.call(your)
看完之后是不是有点懵?一上来就给代码?下面会进行讲解,请专注于“为什么”
大致意思是这个代码的对象可以重复使用identify()和speak()声明函数;
那如果不用this呢?是不是也可以使用identify()和speak()声明函数?答案肯定是yes
列如:
function identify(context){
return context.name.toUpperCase()
}
function say(context){
var gree = '我是'+ identify(context)
console.log(gree)
}
var me = {
name: 'luck'
}
var your = {
name :"lucy"
}
console.log(identify(me))
say(your)
第二个代码是传了一个参数从而使用了identify()和speak()声明函数 但复用率不高,相比之下,this是一种隐式的传递,复用率极高
因此,你知道我们为什么要使用this关键词了吗?(PS: this是一种隐式的传递一个对象的引用,复用率极高,简单明了)
二、对this的误解
1.误解一
在英文层面上,this是指向自身的
NO!这是一个错误的想法
下面一段代码(示列)来进行解释
function test(){
var a = 1
console.log(this.a)//2
}
var a = 2
test()
很显然,this.a = 2 ,指向了外界?
想一想,this指向什么?
下面的一行代码你就会明白了
console.log(this === window)//true
答对了,this指向的是window
那下面我们来记录一下函数foo被调用了几次?思考一下这个代码
function foo(num){
console.log('foo:'+ num)
this.count++
}
foo.count = 0
var i;
for(i = 0 ; i < 10 ;i++){
if(i>5){
foo(i)
}
}
console.log(foo.count)
显然,foo被调了4次,但为什么是0?
this并不是指向那个函数对象(foo.count)的,z只是属性名相同而已,根对象却不相同,其实this指向全局,这段代码无意中创建了一个全局变量count,他的值是Nan
遇到这种我们怎么解决他呢?
function foo(num){
console.log('foo:'+ num)
foo.count++
}
foo.count = 0
var i;
for(i = 0 ; i < 10 ;i++){
if(i>5){
foo(i)
}
}
console.log(foo.count)
直接引用函数名,不要this不就得了吗
哈哈哈,我真的是一个机灵鬼 ,但跑题了跑题了
究竟怎么让this在函数中运用呢?
下面一段代码(示列)来进行解决
function foo(num){
console.log('foo:'+ num)
this.count++
}
foo.count = 0
var i;
for(i = 0 ; i < 10 ;i++){
if(i>5){
foo.call(foo,i)
}
}
console.log(foo.count)
当然是使用call()可以确保this指向函数对象foo本身 注意:在当前调用方式下,this确实指向foo
总而言之,误解一已经解除,this并不是指向本身的,而是在没有使用调用方式下,this指向window(全局)
2.误解二
在作用域的情况下,this指向函数的作用域的
这个想法也是错误的
需要明确的是在任何情况下,this是不指向函数的词法作用域的
虽然在JS内部作用域和对象类似,标识符都是他的属性,但作用域“对象”是无法通过JS代码访问的,他存在于内部;
思考下面一段代码(示列)
function foo(){
var a = 1
this.bar()
}
function bar(){
console.log(this.a)//undefined
}
foo()
显然,this联通foo()和 bar()的词法作用域,想让bar()能访问到foo()里面的a变量。这是不可能实现的,使用this不可能在词法作用域中查找到什么
注意:想要把this与词法作用域的查找混合使用事务,一定要提醒自己,这是无法实现的
所以,误解二也解除了;
三、this到底是什么?
在排除误解之后,this到底是一个什么机制?
this是运行时进行绑定的,并不是编写时进行绑定的;
this的绑定和函数声明位置没有任何关系,只取决与函数的调用方式;
当一个函数被调用了,会创建一个活动记录 (有时候也称为上下文,比如me和your是上下文)。这个记录包含函数在哪里被调用(调用栈),函数的调用方式、传入的参数等信息;this就是这个记录的一个属性,会在函数执行的过程中用到;
下一篇会学到如何查找函数的调用位置,从而在判断函数在执行过程中会绑定this;
总结
- 相对比词法作用域时,this一种隐式的传递一个对象的引用,复用率高,简单明了
- this有常见的两个错误 第一是this指向本身 (错误! this在不被函数调用方式时,是指向window全局);第二是this指向函数作用域(错误!不要把this和词法作用域的查找混合使用,是实现不了的)
- this在运行中进行绑定时,与函数声明的位置没有关系,只取决于函数的调用方式