摘要:遵循以下规则,按优先级排列。换句话说,当处于被调用函数的左边,则就是左边的对象。试一下通过两种不同的方式调用函数时的值。找到应用的规则很显然应用的是规则使用符号。在使用工具库时发现取值不符合上述规则时,请查看库文档。
翻译自文章The Simple Rules to ‘this’ in Javascript。
确定什么是 this 并非难事。总的来说,通过查找函数被调用时的位置(和方法)就可以决定。遵循以下规则,按优先级排列。
规则
通过 new 关键字调用构造函数,函数内的 this 是一个全新的对象。
function ConstructorExample() { console.log(this); this.value = 10; console.log(this); } new ConstructorExample(); // -> {} // -> { value: 10 }
通过 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 }
如果一个函数作为对象的方法调用,即使用 . 符号调用该函数, this 是调用该函数的对象。换句话说,当 . 处于被调用函数的左边,则 this 就是左边的对象。
var obj = { value: 5, printThis: function() { console.log(this); } }; obj.printThis(); // -> { value: 5, printThis: ƒ }
如果函数作为普通函数调用,意味着调用方式不符合以上任意一种, this 就是全局对象。在浏览器中就是 window 。
function fn() { console.log(this); } // If called in browser: fn(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}
*这个规则可以类比于规则3——不同之处在于这个函数自动挂载到了 window 对象上,所以可以这么理解,当我们调用 fn() 时其实调用的事 window.fn() ,所以 this 就是 window 。
console.log(fn === window.fn); // -> true
如果符合上述多个规则,则越前面的规则会决定 this 的值。
如果函数是一个 ES2015 箭头函数,会忽略上述所有规则, this 设置为它被创建时的上下文。为了找到 this 的值,需要找到函数被创建时的环境中 this 的值。
const obj = { value: "abc", createArrowFn: function() { return () => console.log(this); } }; const arrowFn = obj.createArrowFn(); arrowFn(); // -> { value: "abc", createArrowFn: ƒ }
我们返回去看规则3,当我们调用 obj.createArrowFn() 时, createArrowFn 中的 this 就是 obj 对象,我们用 . 符号调用。如果我们在全局中创建一个箭头函数, 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() 很显然应用的是规则3——使用 . 符号。 print() 应用了规则4,在调用 print() 时,我们没有使用 new 、 bind/call/apply 或 . 符号,所以这里的 this 是全局对象 window 。
多重规则应用如上文提到,当应用多个规则时,优先应用前面的规则。
var obj1 = { value: "hi", print: function() { console.log(this); }, }; var obj2 = { value: 17 };
如果规则2和3同时应用,规则2优先。
obj1.print.call(obj2); // -> { value: 17 }
如果规则1和3同时应用,规则1优先。
new obj1.print(); // -> {}关于工具库
一些 JavaScript 库有时候会在函数中主动绑定它认为最有用的内容到 this 上。比如在 JQuery中,在触发事件时 DOM 元素被绑定到了 this 上。在使用工具库时发现取值不符合上述规则时,请查看库文档。很可能使用了 bind 语法。
该文章首发于我的个人站点
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/94366.html
摘要:过去滚动捕捉只能通过实现,但现在得益于新的滚动捕捉模块,这种效果已经可以通过实现了。同时令人庆幸的是浏览器可以根据用户的滚动方式自动控制并判断是否利用捕捉点捕捉。 特别声明,本文翻译自@alligatorio的Control Page Scroll in CSS Using Scroll Snapping一文,受限于译者能力,译文或存在不足,欢迎大家指出。如需转载,烦请注明出处。 滚...
摘要:过去滚动捕捉只能通过实现,但现在得益于新的滚动捕捉模块,这种效果已经可以通过实现了。同时令人庆幸的是浏览器可以根据用户的滚动方式自动控制并判断是否利用捕捉点捕捉。 特别声明,本文翻译自@alligatorio的Control Page Scroll in CSS Using Scroll Snapping一文,受限于译者能力,译文或存在不足,欢迎大家指出。如需转载,烦请注明出处。 滚...
摘要:被解构的数据项位于赋值运算符的右侧,可以是任何数组和对象的组合,允许随意嵌套。数组模式位于赋值运算符的左侧,被结构的数组在其右侧。 解构是ES6的新特性,用于从JavaScript对象和数组中提取数据,语法上比ES5所提供的更加简洁、紧凑、清晰。它不仅能减少你的代码量,还能从根本上改变你的编码方式。用的越多,你就会发现越多塑造数据和函数的方式,这些实现方式在过去几乎是不可能的。本文将深...
摘要:每个字节后必须跟一个响应位。低速率一般是同一个板子上的两个芯片间通信,数据量不大,速率低。速率几百,速率可能不同,不能超过的最高速率。 介绍:I2C通讯协议(Inter-Integrated Circuit)引脚少,硬件实现简单,可扩展性强,不需要USART、CAN等通讯协议的外部收发设备,...
阅读 2269·2021-11-23 10:09
阅读 2791·2021-10-12 10:11
阅读 2574·2021-09-29 09:35
阅读 1318·2019-08-30 15:53
阅读 2239·2019-08-30 11:15
阅读 2888·2019-08-29 13:01
阅读 2270·2019-08-28 18:15
阅读 3338·2019-08-26 12:13