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 相关文章推荐
div+css布局的图片连续滚动js实现代码
May 04 Javascript
页面定时刷新(1秒刷新一次)
Nov 22 Javascript
深入探讨JavaScript、JQuery屏蔽网页鼠标右键菜单及禁止选择复制
Jun 10 Javascript
JavaScript学习笔记之数组的增、删、改、查
Mar 23 Javascript
Javascript中arguments对象的详解与使用方法
Oct 04 Javascript
js仿京东轮播效果 选项卡套选项卡使用
Jan 12 Javascript
jQuery查找dom的几种方法效率详解
May 17 jQuery
node.js中fs文件系统目录操作与文件信息操作
Feb 24 Javascript
vue组件数据传递、父子组件数据获取,slot,router路由功能示例
Mar 19 Javascript
详解Vue.js中引入图片路径的几种方式
Jun 17 Javascript
layui前端时间戳转化实例
Nov 15 Javascript
使用vuex较为优雅的实现一个购物车功能的示例代码
Dec 09 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 expects parameter 1 to be resource, array given 错误
2011/03/23 PHP
php后台如何避免用户直接进入方法实例
2013/10/15 PHP
ThinkPHP2.0读取MSSQL提示Incorrect syntax near the keyword 'AS'的解决方法
2014/06/25 PHP
php实现的Timer页面运行时间监测类
2014/09/24 PHP
thinkPHP3.x常量整理(预定义常量/路径常量/系统常量)
2016/05/20 PHP
php自定义中文字符串截取函数substr_for_gb2312及substr_for_utf8示例
2016/05/28 PHP
Javascript之文件操作
2007/03/07 Javascript
IE6图片加载的一个BUG解决方法
2010/07/13 Javascript
jquery Mobile入门—多页面切换示例学习
2013/01/08 Javascript
js向上无缝滚动,网站公告效果 具体代码
2013/11/18 Javascript
jQuery插件分享之分页插件jqPagination
2014/06/06 Javascript
javascript消除window.close()的提示窗口
2015/05/20 Javascript
Node.js用readline模块实现输入输出
2016/12/16 Javascript
利用HTML5+Socket.io实现摇一摇控制PC端歌曲切换
2017/01/13 Javascript
浅谈javascript的闭包
2017/01/23 Javascript
详解基于vue的服务端渲染框架NUXT
2018/06/20 Javascript
微信小程序按顺序同步执行的两种方式
2019/12/20 Javascript
vue style width a href动态拼接问题的解决
2020/08/07 Javascript
[06:13]DOTA2进化论(修改版)
2013/10/08 DOTA
Python tempfile模块学习笔记(临时文件)
2014/05/25 Python
python中lambda与def用法对比实例分析
2015/04/30 Python
Python中的os.path路径模块中的操作方法总结
2016/07/07 Python
Python3生成手写体数字方法
2018/01/30 Python
python中sys.argv函数精简概括
2018/07/08 Python
Python单元和文档测试实例详解
2019/04/11 Python
anaconda中更改python版本的方法步骤
2019/07/14 Python
Python 合并多个TXT文件并统计词频的实现
2019/08/23 Python
Python socket处理client连接过程解析
2020/03/18 Python
CSS3提交意见输入框样式代码
2014/10/30 HTML / CSS
实例讲解使用HTML5 Canvas绘制阴影效果的方法
2016/03/25 HTML / CSS
判断单链表中是否存在环
2012/07/16 面试题
无私奉献演讲稿
2014/09/04 职场文书
监考失职检讨书
2015/01/26 职场文书
大班下学期个人总结
2015/02/13 职场文书
2016幼儿园教师节新闻稿
2015/11/25 职场文书
go设置多个GOPATH的方式
2021/05/05 Golang