js之this指向规则
1.在浏览器环境中,this在全局作用域下指向window对象,nodejs里面指向global对象
2.函数中三种不同的指向
// 定义一个函数 function foo() { console.log(this); }
不同的环境指向不同的对象
// 直接调用 foo(); //window/global对象 // 放在对象里使用 let obj = { name:"why", foo:foo } obj.foo(); //obj对象 // 通过call/apply调用 foo.call("abc"); // String{"abc"}对象
3.绑定方式
3a 默认绑定,也就是独立的函数调用this或者函数作为参数传入另外一个函数,这时候this都是默认绑定的全局对象
function test1() { console.log(this); // window test2(); } function test2() { console.log(this); // window test3() } function test3() { console.log(this); // window } test1();
3b 隐式调用,也就是某个对象发起的函数调用this。
function foo() { console.log(this); } var obj1 = { name: "obj1", foo: foo } var obj2 = { name: "obj2", obj1: obj1 } obj2.obj1.foo(); // obj1
注意下面的调用方式是默认绑定
var bar = obj1.foo; bar();
3c 显示绑定
也就是通过call和apply方法来绑定this。但是注意调用的对象内部有一个函数的引用,否则会报错
function foo() { console.log(this); } foo.call(global); // 全局对象 foo.call({name: "aaa"}); // {name: "aaa"} foo.call(123); // Number对象,存放是123
bind函数(其实就是Function.prototype.bind)可以将一个函数显示绑定到一个对象上
function foo() { console.log(this); } var obj = { name: "aaa" } var bar = foo.bind(obj); bar(); // obj对象 bar(); // obj对象
3d 特殊的内置函数
在JS的一些内置函数里面,this指向会有一些不一样。
setTimeout的函数参数里面的this指向的是全局对象,forEach默认下也是全局对象,但是可以传入第二参数来指定this绑定的对象。
还有在Dom操作中,操作函数中的this指向的是节点对象
var box = document.querySelector(".box"); box.onclick = function() { console.log(this); // box对象 }
3e new关键字绑定
使用new关键字调用函数时,创建的新对象会被执行prototype连接,然后绑定到函数调用的this上,如果函数没有返回其他对象,表达式会返回这个新对象。
// 创建Person function Person(name) { console.log(this); // Person {} this.name = name; } var p = new Person("aaa"); console.log(p); // Person {name: "aaa"}
4 优先级
默认绑定最低,显示大于隐式,new高于隐式和显示。
5 其他情况
5.1显示绑定时传入的是null或者undefined,那么这个显示绑定就被忽略使用默认绑定
5.2 间接函数引用,使用默认绑定
首先知道(num1=num2)的结果是num2
function foo() { console.log(this); } var obj1 = { name: "obj1", foo: foo }; var obj2 = { name: "obj2" } obj1.foo(); // obj1对象 // ()里面的结果是foo函数 (obj2.foo = obj1.foo)(); // window/global
5.3 箭头函数
箭头函数没有作用域,不使用上述规则,而是根据外层作用域来决定this的指向
几个面试题地址:https://mp.weixin.qq.com/s/hYm0JgBI25grNG_2sCRlTA