this的五种指法
this 到底指向哪里
以下如果没提及,则为严格模式。
js中作用域有两种:
- 词法作用域
- 动态作用域
词法作用域
词法作用域指在书写代码时就被确定的作用域。
看如下代码
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();// 结果是1
动态作用域
动态作用域指在代码运行时才被确定的作用域。
js中只有this的作用域是动态作用域
this的五种绑定
初学js时,会想当然认为this遵循某一条规律,就像物理学那样,然而并不是。
this的绑定分为五种情况,这五种情况之间毫无规律可言。不过好在都很简单。
一. 默认绑定
当以如下形式执行一个函数时,this为默认绑定;
func()
- 严格模式下,this为undefined
- 非严格模式下,this是全局对象。
与函数调用嵌套多少层如何嵌套无关
/* 全是undefined */
function printThis(){
return this
}
var obj = {
say(){
console.log('obj.say',printThis())
}
}
function funcB(){
console.log('funcB',printThis());
obj.say();
}
console.log('funcA',printThis())
obj.say()
funcB()
二. 隐式绑定
当以如下行驶执行一个函数时,this为隐式绑定;
a.b.func()
此时this指向点前面一个对象
赋值会改变隐式绑定this的指向
- 方法赋值给变量
class T {
dotInvoke() {
console.log('dotInvoke', this.sayThis())
}
sayThis() {
return this
}
assignInvoke() {
var sayThis = this.sayThis;
console.log('assignInvoke', sayThis())
}
}
var tt = new T();
tt.dotInvoke()// 指向T
tt.assignInvoke()// undefined
- 函数被赋值成方法
function printThis(){
return this
}
var obj = {};
obj.say = printThis;
obj.say()/* 指向obj */
- 赋值给参数
极为常见的是回调函数的this是undefined,因为回调函数被复制给参数,参数再调用时变成了默认绑定
function asyncFun(cb){
cb()
}
var obj = {
callback(){
console.log(this)
}
}
obj.callback()/*隐式绑定 obj */
asyncFun(obj.callback);/*默认绑定 undefined */
三. 箭头函数
箭头函数会让this指向最近的函数或全局作用域
- 与最近的函数的this指向相同
function foo() {
// 返回一个箭头函数
return (a)=>{
//this 继承自 foo()
return this.a
}
;
}
var obj1 = {
a: 'obj1'
};
var obj2 = {
a: 'obj2'
}
var arrow1 = foo.call(obj1);
var arrow2 = foo.call(obj2);
var arrow3 = foo();
console.log('arrow1',arrow1())/* obj1 */
console.log('arrow2',arrow2())/* obj2 */
console.log('arrow3',arrow3())/* undefined,严格模式下报错 */
- 指向全局
var printThis = ()=>this;
console.log('printThis',printThis());/* global */
- 指向实例
class Test {
printThis = ()=>{
return this
}
}
//会被babel翻译成
var test = function test() {
var _this = this;
this.printThis = function () {
return _this;
};
};
四. 显示绑定
call, apply, bind指定this指向
五. new绑定
构造函数,ES6中的class
new构造函数,new class时,this指向实例
总结
- 五种绑定,后面两种情况单一,前面两种会因为方法,函数被赋值而互相转化。
- 因为this处于动态作用域,而目前开发时又大量使用框架。我们写下的代码,并不总是由我们自己调用,而是被打包工具打包后,由框架调用。导致我们并不知道我们写下的函数和方法是否被框架复制过或显示绑定过而改变了this指向。以至this指向更加扑朔迷离。
- 写完本文顿时觉得,python里指向明确的self完爆js的this。
来源:https://segmentfault.com/a/1190000017715350
this的五种指法的更多相关文章
- JavaScript常见的五种数组去重的方式
▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN ...
- Android之数据存储的五种方法
1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...
- 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- xmlHttp.readyState的五种状态
自己简单的总结一下 深入的了解可以看其他道友的 O(∩_∩)O readyState有五种可能的值: 0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法. ...
- Redis五种数据结构简介
Redis五种结构 1.String 可以是字符串,整数或者浮点数,对整个字符串或者字符串中的一部分执行操作,对整个整数或者浮点执行自增(increment)或者自减(decrement)操作. 字符 ...
- Android中Button的五种监听事件
简单聊一下Android中Button的五种监听事件: 1.在布局文件中为button添加onClick属性,Activity实现其方法2.匿名内部类作为事件监听器类3.内部类作为监听器4.Activ ...
- 五种方式让你在java中读取properties文件内容不再是难题
一.背景 最近,在项目开发的过程中,遇到需要在properties文件中定义一些自定义的变量,以供java程序动态的读取,修改变量,不再需要修改代码的问题.就借此机会把Spring+SpringMVC ...
- php五种常见的设计模式(转载)
很多人都想着写博客来记录编程生活中的点滴,我也不例外,但想了好长时间不知道写什么........万事开头难,先转载一篇吧..... 设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Ga ...
- Android_安卓为按钮控件绑定事件的五种方式
一.写在最前面 本次,来介绍一下安卓中为控件--Button绑定事件的五种方式. 二.具体的实现 第一种:直接绑定在Button控件上: 步骤1.在Button控件上设置android:onClick ...
随机推荐
- org.apache.ibatis.binding.BindingException: Parameter 'xxx' not found. Available parameters are [arg1, arg0, param1, param2]
这个异常说明参数没有加上@Param注解,加上这个注解就行了. 默认情况下mybatis把参数按顺序转化为[0, 1, param1, param2],也就是说#{0} 和 #{param1} 是一样 ...
- SWT图形用户界面之配置
1.在eclipse的plugins目录下找到org.eclipse.swt.win32.win32.x86_64_3.111.0.v20190605-1801.jar文件 其中3.111.0是ecl ...
- 09_springmvc图片上传
一.上传图片 1.需求 在修改商品页面,添加上传商品图片的功能 2.springmvc中对多部件类型解析 在页面form中提交enctype="multipart/form-data&quo ...
- windows系统下jupyter notebook使用虚拟环境
目录 [亲测好使]windows系统下jupyter notebook使用虚拟环境 在虚拟环境中安装jupyter,并添加到jupyter kernel 参考 [未测试,但觉得比上面那方法好,因为上面 ...
- tomcat下面部署多个项目
最近需要部署多个项目,我目前所知道的两种方法,第一种是一个tomcat部署一个项目,需要布置多个tomcat就可以部署多个项目.第二种就是一个tomcat下面部署多个项目. 首先我们先来说说两种的优劣 ...
- Python全栈开发:装饰器实例
#!/usr/bin/env python # -*- coding;utf-8 -*- """ 1.将outer函数放入内存 2.遇见@ + 函数名,则将该函数转换为装 ...
- ODOO/OPENERP的网页模块QWEB简述
1.web 模块 注意,OpenERP 模块中 web 部分用到的所有文件必须被放置在模块内的 static 文件夹里.这是强制性的,出于安全考虑. 事实上,我们创建的文件夹 CSS,JS 和 XML ...
- 杂项-公司:Oracle
ylbtech-杂项-公司:Oracle 甲骨文公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩.1989年正式进入中国市场.201 ...
- iOS程序两中启动图方式和一些坑LaunchImage 和 Assets.xcassets(Images.xcassets)
一.通过LaunchScreen.storyboard 作启动图 1>在LaunchScreen.storyboard中拖拽一个imageView放上启动图片 注意:记得勾选右边的 User a ...
- R语言数据预处理
R语言数据预处理 一.日期时间.字符串的处理 日期 Date: 日期类,年与日 POSIXct: 日期时间类,精确到秒,用数字表示 POSIXlt: 日期时间类,精确到秒,用列表表示 Sys.date ...