在大多情况下,this出现在函数中。this指向什么,跟函数定义的位置无关,跟函数调用方式有关(绑定规则相关)。
function foo(){ console.log(this); } var obj = { foo: foo } //不同的调用方式this的指向不同,不同的调用方式对应着不同的绑定规则 foo();//window obj.foo();//obj foo.call("123");//String{"abc"}
this的绑定规则
function fn() { console.log(this); } fn.bind(123).apply(321);
function Fn(){ console.log(this); } fn.bind("132"); var obj = new Fn();
绑定优先级:new 绑定 > 显示绑定 > 隐式绑定 > 默认绑定
忽略显示绑定
apply/call/bind:当传入null/undefined时,自动将this绑定成全局对象
function fn(){ console.log(this); } fn.apply(null); fn.apply(undefined);
间接函数引用
var obj1 = { foo: function(){ console.log(this); } } var obj2 = {} ;(obj2.bar = obj1.foo)()//括号中包含赋值表达式,属于独立函数调用,是默认绑定,指向window
箭头函数 将头函数不会绑定this,arguments属性箭头函数不能作为构造函数来使用(不能new对象) 简写
var nums = [0, 1, 2, 3, 4, 5]; var result = nums .filter(item => item % 2 === 0) .map(item => item * 10) .reduce((preVal, curVal) => preVal + curVal, 0); console.log(result);
var foo = () => ({ name: "foo", age: 18 });//这样解析时会将对象当作一个整体
箭头函数不遵循this的四种标准规则,箭头函数内部没有绑定this,也不能通过call/apply/bind绑定this,箭头函数的this指向根据外层作用域决定
var obj = { getData() { setTimeout(function () { console.log(this); }, 200); }, }; //setTimeout中的函数属于独立调用,所以指向的是window //如果想让this指向obj对象,setTimeout中使用箭头函数 obj.getData();
面试题一:
var name = "window"; var person = { name: "person", sayName: function () { console.log(this.name); } }; function sayName() { var sss = person.sayName; sss(); person.sayName(); (person.sayName)(); (b = person.sayName)(); //包含赋值表达式,属于间接函数引用 } sayName();
答案:window(默认绑定)、person(隐式绑定)、person(隐式绑定)、window(间接函数引用)
面试题二:
var name = 'window' var person1 = { name: 'person1', foo1: function () { console.log(this.name) }, foo2: () => console.log(this.name), foo3: function () { return function () { console.log(this.name) } }, foo4: function () { return () => { console.log(this.name) } } } var person2 = { name: 'person2' } person1.foo1(); person1.foo1.call(person2); person1.foo2(); person1.foo2.call(person2); person1.foo3()(); person1.foo3.call(person2)(); person1.foo3().call(person2); person1.foo4()(); person1.foo4.call(person2)(); person1.foo4().call(person2);
答案解析:
person1.foo1(); //person1:隐式绑定 person1.foo1.call(person2); //person2:显示绑定 person1.foo2();//window:箭头函数的this指向上层作用域的this person1.foo2.call(person2);//window:箭头函数的this指向上层作用域的this,且不能改变箭头函数指向 person1.foo3()();//window:先执行person1.foo3(),然后拿到返回的函数再调用,属于独立调用,所以指向window person1.foo3.call(person2)();//window:先执行person1.foo3.call(person2),拿到返回的函数再调用,属于独立调用 person1.foo3().call(person2);//person2:先执行person1.foo3(),拿到返回的函数通过call调用this指向了person2 person1.foo4()(); //person1:拿到返回的箭头函数后,箭头函数没有this,根据上层作用域决定,上层foo4函数指向的是person1对象(foo4是被person1直接调用的),所以内部箭头函数也指向peroson1 person1.foo4.call(person2)(); //person2:给foo4绑定this为person2,箭头函数调用this指向上层作用域,上层foo4的this被显示绑定为了person2,那么内部的箭头函数也是指向person2 person1.foo4().call(person2); //person1:call调用箭头函数,依然去上一层找,所以依然是person1
面试题三:
var name = 'window' function Person (name) { this.name = name this.foo1 = function () { console.log(this.name) }, this.foo2 = () => console.log(this.name), this.foo3 = function () { return function () { console.log(this.name) } }, this.foo4 = function () { return () => { console.log(this.name) } } } var person1 = new Person('person1') var person2 = new Person('person2') person1.foo1() person1.foo1.call(person2) person1.foo2() person1.foo2.call(person2) person1.foo3()() person1.foo3.call(person2)() person1.foo3().call(person2) person1.foo4()() person1.foo4.call(person2)() person1.foo4().call(person2)
答案与解析:
person1.foo1() //person1 person1.foo1.call(person2) //person2 person1.foo2() //person1:箭头函数,指向上层作用域的this,上层作用域是“Person构造函数” person1.foo2.call(person2) //person1::箭头函数,指向上层作用域的this,不能被显示绑定 person1.foo3()() //window:拿到返回的函数后调用,属于独立调用 person1.foo3.call(person2)() //window:拿到返回的函数后调用,属于独立调用 person1.foo3().call(person2) //person2:通过call显示绑定 person1.foo4()() //person1:返回的箭头函数去上层作用域找,上层foo的this指向person1 person1.foo4.call(person2)()//person2:返回的箭头函数去上层作用域找,上层this通过call指向了person2 person1.foo4().call(person2)//person1:箭头函数的this不能被显示绑定
面试题四:
var name = 'window' function Person (name) { this.name = name this.obj = { name: 'obj', foo1: function () { return function () { console.log(this.name) } }, foo2: function () { return () => { console.log(this.name) } } } } var person1 = new Person('person1') var person2 = new Person('person2') person1.obj.foo1()() person1.obj.foo1.call(person2)() person1.obj.foo1().call(person2) person1.obj.foo2()() person1.obj.foo2.call(person2)() person1.obj.foo2().call(person2)
答案与解析:
person1.obj.foo1()() //window:独立调用 person1.obj.foo1.call(person2)() //window:独立调用 person1.obj.foo1().call(person2) //person2:call显示绑定 person1.obj.foo2()() //obj:返回的是箭头函数,this由上层作用域foo2函数决定,foo2的this指向obj(foo2是被obj直接调用的),所以返回的箭头函数this也是指向obj person1.obj.foo2.call(person2)()//person2:箭头函数上层作用域this被call指向person2,所以箭头函数也是指向person2 person1.obj.foo2().call(person2)//obj:箭头函数this不能被显示绑定
到此这篇关于深入了解JavaScript中的this关键字指向的文章就介绍到这了,更多相关JavaScript中的this内容请搜索插件窝以前的文章或继续浏览下面的相关文章希望大家以后多多支持插件窝!