JavaScript 中的 this 简单规则


Posted in Javascript onSeptember 19, 2017

几条规则确定函数里的 this 是什么。

想确定 this 是什么其实非常简单。总体的规则是,通过检查它的调用位置,在函数被调用的的时候确定 this。它遵循下面这些规则,接下来以优先级顺序说明。

规则

1、如果在调用函数时使用 new 关键字,那么函数里的 this 就是一个全新的对象。

function ConstructorExample() {
  console.log(this);
  this.value = 10;
  console.log(this);
}
new ConstructorExample();
// -> {}
// -> { value: 10 }

2、如果使用 apply、call 或者 bind 调用函数,那么函数里的 this 就是作为参数传进去的对象。

function fn() {
  console.log(this);
}
var obj = {
  value: 5
};
var boundFn = fn.bind(obj);
boundFn();   // -> { value: 5 }
fn.call(obj); // -> { value: 5 }
fn.apply(obj); // -> { value: 5 }

3、如果函数作为一个方法调用,就是说如果使用点符号调用函数,那么 this 就是拥有这个函数作为属性的对象。换句话说,当一个点在函数调用的左侧时,this 就是这个点左侧的那个对象。

var obj = {
  value: 5,
  printThis: function() {
    console.log(this);
  }
};
obj.printThis(); // -> { value: 5, printThis: ƒ }

4、如果函数作为一个纯粹的函数调用,也就是说,它在没有上述任何条件的情况下被调用,那么 this 就是全局对象。在浏览器里,就是 window 对象。

function fn() {
  console.log(this);
}
// 如果在浏览器里调用:
fn(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

注意这个规则其实和第三个规则是一样的,区别在于没有声明为方法的函数会自动成为全局对象 window 的属性。因此,这其实是一个隐式的方法调用。当我们调用 fn(),其实就会被浏览器理解为 window.fn(),所以 this 就是 window。

console.log(fn === window.fn); // -> true

5、如果上述规则有多个适用,那么优先级更高的就会设置 this 值。

6、如果是 ES2015 里的箭头函数,那么它将忽略上述所有规则,并在创建的时候接收包含它的作用域作为 this 的值。想确定 this 具体是什么的话,只需从创建箭头函数那里往上一行,看看那儿的 this 是什么,箭头函数里的 this 值和它一样。

const obj = {
  value: 'abc',
  createArrowFn: function() {
    return () => console.log(this);
  }
};
const arrowFn = obj.createArrowFn();
arrowFn(); // -> { value: 'abc', createArrowFn: ƒ }

看回第三个规则,当我们调用 obj.createArrowFn() 的时候,createArrowFn 里的 this 是 obj,因为这是方法调用。因此,obj 会在 arrowFn 里绑定到 this 上。如果我们在全局作用域创建一个箭头函数,那么 this 值就会是 window。

应用规则

让我们来看一个代码示例,并应用这些规则。尝试一下看能否弄清楚不同的函数调用下,this 是什么。

确定应用了哪条规则

var obj = {
  value: 'hi',
  printThis: function() {
    console.log(this);
  }
};
var print = obj.printThis;
obj.printThis(); // -> {value: "hi", printThis: ƒ}
print(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

obj.printThis() 属于第三条规则,方法调用。另一方面,print() 属于第四条规则,纯粹的函数调用。对于 print() 来说,我们在调用的时候没有使用 new、bind/call/apply 或者点符号,所以它对应了规则四,this 就是全局对象 window。

当适用多个规则的时候

当适用多个规则的时候,使用列表里更高优先级的规则。

var obj1 = {
  value: 'hi',
  print: function() {
    console.log(this);
  },
};
var obj2 = { value: 17 };

如果规则二和规则三同时适用,那么规则二占优。

obj1.print.call(obj2); // -> { value: 17 }

如果规则一和规则三同时适用,那么规则一占优。

new obj1.print(); // -> {}

有些库有时候会故意将 this 值绑定到某些函数里。而通常会在函数里将最有用的值绑定到 this 上使用。举个例子,jQuery 把 this 绑定到 DOM 元素上,在回调中触发一个事件。如果某个库出现一个不太符合上述规则的 this 值,那么请仔细阅读这个库的文档,它很有可能使用 bind 绑定了。

总结

以上所述是小编给大家介绍的JavaScript 中的 this 简单规则,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript FormatNumber函数实现方法
Dec 30 Javascript
javascript下4个跨浏览器必备的函数
Mar 07 Javascript
Firefox中beforeunload事件的实现缺陷浅析
May 03 Javascript
js中一个函数获取另一个函数返回值问题探讨
Nov 21 Javascript
js浏览器本地存储store.js介绍及应用
May 13 Javascript
JavaScript获取指定元素位置的方法
Apr 08 Javascript
jQuery使用正则表达式替换dom元素标签用法示例
Jan 16 Javascript
jQuery滚动监听实现商城楼梯式导航效果
Mar 06 Javascript
Node+OCR实现图像文字识别功能
Nov 26 Javascript
vue模式history下在iis中配置流程
Apr 17 Javascript
js生成1到100的随机数最简单的实现方法
Feb 07 Javascript
vue tab切换,解决echartst图表宽度只有100px的问题
Jul 19 Javascript
在 Node.js 中使用原生 ES 模块方法解析
Sep 19 #Javascript
Webpack 服务器端代码打包的示例代码
Sep 19 #Javascript
原生js中ajax访问的实例详解
Sep 19 #Javascript
angularjs实现过滤并替换关键字小功能
Sep 19 #Javascript
详解vue-cli与webpack结合如何处理静态资源
Sep 19 #Javascript
前端常见跨域解决方案(全)
Sep 19 #Javascript
详解.vue文件中监听input输入事件(oninput)
Sep 19 #Javascript
You might like
PHP 配置文件中open_basedir选项作用
2009/07/19 PHP
用php获取本周,上周,本月,上月,本季度日期的代码
2009/08/05 PHP
跟我学Laravel之请求与输入
2014/10/15 PHP
浅谈Javascript中的Function与Object
2015/01/26 Javascript
JavaScript汉诺塔问题解决方法
2015/04/21 Javascript
javaScript事件机制兼容【详细整理】
2016/07/23 Javascript
vue学习笔记之v-if和v-show的区别
2017/09/20 Javascript
解决vue 更改计算属性后select选中值不更改的问题
2018/03/02 Javascript
vue使用axios上传文件(FormData)的方法
2019/04/14 Javascript
angular4应用中输入的最小值和最大值的方法
2019/05/17 Javascript
微信小程序身份证验证方法实现详解
2019/06/28 Javascript
微信小程序 (地址选择1)--选取搜索地点并显示效果
2019/12/17 Javascript
JavaScript ECMA-262-3 深入解析(一):执行上下文实例分析
2020/04/25 Javascript
如何在vue 中引入使用jquery
2020/11/10 jQuery
[17:00]DOTA2 HEROS教学视频教你分分钟做大人-帕克
2014/06/10 DOTA
[46:20]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
python创建只读属性对象的方法(ReadOnlyObject)
2013/02/10 Python
从零学python系列之教你如何根据图片生成字符画
2014/05/23 Python
剖析Python的Tornado框架中session支持的实现代码
2015/08/21 Python
python使用scrapy发送post请求的坑
2018/09/04 Python
django 扩展user用户字段inlines方式
2020/03/30 Python
Django admin 实现search_fields精确查询实例
2020/03/30 Python
关于keras.layers.Conv1D的kernel_size参数使用介绍
2020/05/22 Python
如何用Python徒手写线性回归
2021/01/25 Python
美国批发零售网站:GearXS
2016/07/26 全球购物
Tory Burch英国官方网站:美国时尚生活品牌
2017/12/06 全球购物
美国儿童玩具、装扮和玩偶商店:Magic Cabin
2018/09/02 全球购物
ORLY官网:美国专业美甲一线品牌
2019/12/11 全球购物
医学专业五年以上个人求职信
2013/12/03 职场文书
消防安全责任书
2014/04/14 职场文书
杭州黄龙洞导游词
2015/02/10 职场文书
学校少先队工作总结
2015/08/12 职场文书
敬业奉献模范事迹材料(2016精选版)
2016/02/26 职场文书
写自招自荐信的绝招!
2019/04/19 职场文书
Redis Cluster 集群搭建你会吗
2021/08/04 Redis
MySQL分区以及建索引的方法总结
2022/04/13 MySQL