JavaScript中的this
来源:互联网 发布:jmeter调用java代码 编辑:程序博客网 时间:2024/06/02 21:29
学习JavaScript的时候,this曾让我困惑不已,因为不清楚this所指向的是什么,在阅读一些代码的时候总是迷迷糊糊,不知所云。弄懂this后,看JavaScript代码的时候比原来更清晰,对语言本身也有了更深的理解。在JavaScript中,this非常重要但又特别容易弄错,所以我在此总结一下this的点点滴滴,希望能给那些对this还不明白的朋友们一点帮助吧。
- 一this的起源
- 二对this的误解
- 三this真正的指向
- 隐式绑定
- 显式绑定
- new绑定
- 默认绑定
- 四this绑定优先级
- 五值得注意的几个点
- 小心隐性绑定
- 箭头函数
一、this的起源
了解this
是怎么来的,对更好地理解this
还是很重要的。
当一个函数被调用的时候,也就是执行流进入一个函数的时候,会自动创建一个被称为执行上下文的记录(其实这个时候也就产生了作用域链),这个记录里包含了各种必要信息,比如函数的调用方式,函数的参数(也就是arguments
)等,this
就包含在这个信息里。
二、对this的误解
我刚接触this的时候,我简单地觉得this就是指向函数所在的对象。比如:
var myObj = { message: "Hi, Ontides!", say: function say(){ console.log(this.message); }};myObj.say(); //Hi, Ontides!
这里确实如所预想的那样,打印出了“Hi, Ontides”,但是,函数并不一定在一个对象中,如果是一个全局函数,那么它里面的this指向就不能简单地理解为“指向函数所在的对象”那么了。
实际上,JavaScript中this的指向和this所在函数定义的位置没有任何关系(ES5及以前,因为ES6中的箭头函数不是这样,稍后会说)。我们之所以会认为this和函数所声明的地方有关,是因为在JavaScript中的作用域遵循词法作用域,因此,我们很容易使用词法作用域的分析方式去分析this的具体指向。实际上,this的处理方式和动态作用域的处理方式相同。this的指向取决于函数调用的位置,而不是函数定义的位置。
三、this真正的指向
上面提到,函数调用的位置决定了this绑定的对象。在JavaScript中,对应函数四种调用方式,this的绑定一共有四种方式,分别为隐式绑定,显式绑定、new绑定和默认绑定。
1. 隐式绑定
当函数的调用位置具有上下文对象,或者说函数是在一个对象下调用的时候,this会被隐式绑定到这个上下文对象上。如:
function foo(){ console.log(this.a);}var obj = { a: 2, foo: foo};//这里this指向了objobj.foo() //2
2. 显式绑定
当一个函数使用call
或者apply
的方式调用的时候,this会被显式地绑定到call
或者apply
所指定的对象。如:
var a = 3;function foo(){ console.log(this.a);}var obj = { a: 2};foo.call(obj); //2
这里因为函数foo再调用的时候使用.call()
的方式调用,所以this指向了obj而不是默认的全局对象。
3. new绑定
当对函数进行构造调用的时候(即使用new操作符进行调用),this的指向会发生改变。为了更好阐述new绑定,这里先阐述一下对函数构造调用的的过程。
当对一个函数尽兴构造调用的时候,会经历以下步骤:
- 创建一个新的对象
- 将构造函数的作用域赋给新的对象
- 执行构造函数中的代码
- 返回新对象
在步骤2中this被绑定到了这个新对象。
4. 默认绑定
当前几种绑定都不适用的情况下JavaScript引擎会对this执行默认绑定。这里的函数调用方式是独立函数调用,如:
var a = 1;function foo(){ console.log(this.name);}foo(); //1
在默认绑定的情况下this被绑定到了全局对象,因为全局变量a是全局对象的一个属性,因此这里输出了a中的内容。
这里需要注意的是,再严格模式下,默认绑定将不会绑定到全局对象上,而会绑定到undefined
,如:
"use strict";var a = 2;function foo(){ console.log(this.a);}foo(); //TypeError: undefined is not an object
这里抛出了类型错误的提示,因为this被绑定到undefined
,而undefined
不是一个对象。
四、this绑定优先级
this绑定一共四条规则,那么在判断this绑定的时候应该怎样运用规则呢?通过this绑定的优先级来判断。
优先级从高到低分别为 new绑定 > 显式绑定 > 隐式绑定 > 默认绑定。
五、值得注意的几个点
1. 小心隐性绑定
有些情况一些函数看起来像是隐性绑定,而实际上是应用了默认绑定。如:
var a = 3;function foo(){ console.log(this.a);}var obj = { a: 2, foo: foo};var bar = obj.foo;obj.foo(); //2bar(); //3
这里虽然把obj.foo
赋给了bar
,但是实际上只是把对foo
的引用赋给了bar
,因此这里bar
的调用只是普通的独立函数调用。
还有一种更为常见而容易出错的情况发生在传入回调函数时:
var a = 3;function foo(){ console.log(this.a);}var obj = { a: 2, foo: foo};function doFoo(fn){ fn();}doFoo(obj.foo); //3
同样,如果理解函数名是对函数的引用的话,这个结果就容易理解了呃。传递到doFoo的参数是函数foo,函数的调用方式是独立调用,因此这里的this并不适用隐形绑定规则,而是采用默认绑定的规则。
2. 箭头函数
ES6中的箭头函数不适用与上面四个规则。
关于箭头有两点需要注意:
箭头函数中的this由函数所在的外部作用域来决定的
这里箭头函数中this遵循词法作用域的规则。如:
var a = 2;var obj = { a: 1, foo: function foo(){ setTimeout(()=>{ console.log(this.a); },30); }}obj.foo(); //1
这里定时器中的this并没有指向全局对象,是绑定到obj,可以看出是继承了外层函数中的this的绑定对象。
箭头函数的this绑定无法修改
箭头函数使用自己独特的this绑定原则,不能通过
.call()
等方式改变this指向。
- 【javascript】javascript中的this
- JavaScript中的this指针
- javascript 中的"this"
- javascript中的this!
- Javascript中的this讲解
- Javascript中的this关键字
- javascript中的this
- JavaScript中的this关键字
- JavaScript中的this详解
- JavaScript中的this指针
- javascript中的this
- JavaScript 中的this 关键字
- 有关javascript中的this
- javascript中的this
- JavaScript 中的 this
- Javascript中的this
- javascript中的this
- JavaScript中的this用法
- MarkDown 超链接页面内和通过新窗口打开
- java-多态
- <设计模式21>访问者模式
- 继承
- JS数据类型
- JavaScript中的this
- opencv-python 函数总览(初版)
- 通用的IO流文件读取工具
- 183Q游戏(16)188/193/198/202/206/210/214(17-23)
- 功分器和耦合器以及合路器的区别
- 插入排序基本思路与算法
- Vigenere Decode
- 分布式系统互斥性与幂等性问题的分析与解决
- 【笔记】Nginx+Ngrok实现80端口服务器+80端口内网穿透