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使用eval或者new Function进行语法检查
Oct 16 Javascript
js 立即调用的函数表达式如何写
Jan 12 Javascript
关于jQuery判断元素是否存在的问题示例探讨
Jul 21 Javascript
Javascript之BOM(window对象)详解
May 25 Javascript
JS基于面向对象实现的多个倒计时器功能示例
Feb 28 Javascript
vue.js选中动态绑定的radio的指定项
Jun 02 Javascript
Angular2里获取(input file)上传文件的内容的方法
Sep 05 Javascript
实现Vue的markdown文档可以在线运行的方法示例
Dec 11 Javascript
jQuery+vue.js实现的多选下拉列表功能示例
Jan 15 jQuery
vue组件之间的数据传递方法详解
Apr 19 Javascript
Vue CLI项目 axios模块前后端交互的使用(类似ajax提交)
Sep 01 Javascript
JS数据类型判断的几种常用方法
Jul 07 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调用Twitter的RSS的实现代码
2010/03/10 PHP
PHP采集利器 Snoopy 试用心得
2011/07/03 PHP
PHP通过API获取手机号码归属地
2015/05/28 PHP
PHP读取文件的常见几种方法
2016/11/03 PHP
修改js Calendar日历控件 兼容IE9/谷歌/火狐
2013/01/04 Javascript
jquery快捷动态绑定键盘事件的操作函数代码
2013/10/17 Javascript
如何用jQuery实现ASP.NET GridView折叠伸展效果
2015/09/26 Javascript
实例详解jQuery表单验证插件validate
2016/01/18 Javascript
Java中int与integer的区别(基本数据类型与引用数据类型)
2017/02/19 Javascript
ES6中的rest参数与扩展运算符详解
2017/07/18 Javascript
vue 自定义提示框(Toast)组件的实现代码
2018/08/17 Javascript
Vue文件配置全局变量的实例
2018/09/06 Javascript
webpack实践之DLLPlugin 和 DLLReferencePlugin的使用教程
2019/06/10 Javascript
vue filter 完美时间日期格式的代码
2019/08/14 Javascript
node.JS二进制操作模块buffer对象使用方法详解
2020/02/06 Javascript
Vue中 axios delete请求参数操作
2020/08/25 Javascript
详解python使用Nginx和uWSGI来运行Python应用
2018/01/09 Python
Windows下安装Django框架的方法简明教程
2018/03/28 Python
浅谈Python大神都是这样处理XML文件的
2019/05/31 Python
python顺序执行多个py文件的方法
2019/06/29 Python
pytorch 模型可视化的例子
2019/08/17 Python
python如何编写类似nmap的扫描工具
2020/11/06 Python
Python 利用flask搭建一个共享服务器的步骤
2020/12/05 Python
德国电子商城:ComputerUniverse
2017/04/21 全球购物
台湾租车首选品牌:IWS艾维士租车
2019/05/03 全球购物
Foot Locker澳洲官网:美国运动服和鞋类零售商
2019/10/11 全球购物
中东奢侈品购物网站:Ounass
2020/09/02 全球购物
个人安全生产承诺书
2014/05/22 职场文书
2014年师德承诺书
2014/05/23 职场文书
乡镇爱国卫生月活动总结
2014/06/25 职场文书
反四风个人对照检查材料思想汇报
2014/09/25 职场文书
小学语文教师年度考核个人总结
2015/02/05 职场文书
教师节感想
2015/08/11 职场文书
2016大学军训通讯稿
2015/11/25 职场文书
Spring Cache和EhCache实现缓存管理方式
2021/06/15 Java/Android
SpringBoot深入分析讲解监听器模式下
2022/07/15 Java/Android