接触JavaScript这门语言已有两年多了,刚开始使用时觉着这门语言真是通俗易懂,可以说是代码随着想法而出。但用着用着就发现某些功能与你所想要的结果不同(闭包中的this,对象中的函数,对象上的原型...)。期间在网上查阅各种JavaScript学习资料,其中对this这个关键的内容占了不小的一部分,自己也一直想系统对this相关知识进行梳理梳理,最近项目不是太忙就抽了点时间写一下自己对this的理解,有兴趣的小伙伴可以查阅查阅(各位大神就不必浪费你们宝贵的时间了)。
先来张本文的思维导图:
1.为什么使用this呢?
先看看不使用this和使用this的代码对比:
var me = { name: '小明' } //不使用this function name(context){ console.log("我的名字是"+context.name) } name(me)//我的名字是小明 //使用this function name(){ console.log("我的名字是"+this.name) } name.call(me)//我的名字是小明
显而易见,如果没有this我们就需要给函数显示的传入一个上下文对象。对于不使用this来说,如果我们调用函数时传递的变量越来越复杂,那我们的代码肯定会显得很混乱。反之使用this就不会出现这些情况。 结论:this提供了一种更优雅的方式来隐示的传递一个对象的引用,可以使我们的API设计显得更加简洁和易于复用。
2.常见的对this理解的误区
1).this是指向自身的么? this指向自身,从英语的语法角度可以说的通。但是在JavaScript语法中如果这样理解,就会产生意想不到的bug。 分析如下代码:
foo.myname = "who am I?" function foo(){ this.myname = "I am foo" } foo() console.log(foo.myname)// "who am I?"
如果this是指向自身的话那么输出的应该是 I am foo,然而控制台输出的是"who am I?"。那么this.myname指向的哪里呢?如果此时你在控制台输入console.log(myname)//"I am foo"
,可见我们创建了一个全局变量。关于this是否指向自身的结论一目了然。答案是NO
2).this指向他所处函数(或对象)的作用域么? 思考如下代码:
function foo(){ var a=2; this.bar()//目的为了联通foo和bar的作用域 } function bar(){ console.log(this.a) } foo()//undefined *代码引用你不知道的Javascript上卷80页,有兴趣可以去看看这本书,书中的例子都非常经典*
上述例子是个很经典的js代码片段,表面上看没有什么语法错误。它的错误之处是在于将JavaScript的this和词法作用域混合使用了,因此这段代码是不可能实现的。 结论:无论何时我们都要分清JavaScript中的this和词法作用域是两个不同的概念。
3.this到底是什么?
在JavaScript内部每当js运行时,每一个作用域都会生成一个内部对象,这个内部对象用关键字this表示。这句话总结了this是如何出现的(动态的产生,很符合JavaScript这门语言的动态特点),也说明的this的绑定其实跟他的声明位置没有半毛钱关系,值取决于函数的调用方式。
var obj={ name:"i am obj", func:function (){ console.log(this==obj) } } obj.func()//true
(func:“你是属于我的。”this:“NO,只是暂时住你这而已,我是属于obj的.”)
4.用好this的需要理解什么?
要想将JavaScript中this绑定这个功能化为己用我们还需要理解this的各种调用方式即全局调用和局部调用
1.全局调用(此时为全局上下文)不用多说了,此时this相当于window
console.log(this==window)//true
2.局部调用(此时作为函数上下文)
- 函数调用
function foo(){ console.log(this == window)//true } foo()
此种调用相当于全局调用的结果(符合我们第三节所说的,this的值取决于函数的调用方式),因为调用函数的位置是在全局变量下。
- 方法调用 console.log('Hello World!') 1)对象方法调用
var myname = "window" var obj={ myname:"object", func: function(){ console.log(this.myname) } } obj.func()//"object"
当函数作为对象里的方法被调用时,它们的 this 是调用该函数的对象.
2)bind方法调用
function f(){ return this.a; } var g = f.bind({a:"azerty"});//g是与f具有相同函数体和作用域的函数 console.log(g()); // azerty //此时this至指向{a:"azerty"}
3)构造函数中调用
function foo(){ this.name = "function"; } var o = new foo(); console.log(o.name); //"function"
当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。 关于this的调用方式MDN中的this章节developer.mozilla.org/zh-CN/docs/…说明比较详细,有兴趣的小伙伴可以去看看。