this 的指向
this永远指向最后调用它的对象。this 的值取决于调用的模式
-
方法调用模式
var myObject = { value:0, increment:function(inc){ this.value += typeof inc === 'number'?inc:1; } } myObject.increment(); console.log(myObject.value) //1 myObject.increment(2); console.log(myObject.value) //2 -
函数调用模式
var add = function(a, b) { return a + b; }; myObject.double = function() { var helper = function() { this.value = add(this.value, this.value); console.log(this.value) //NaN }; helper();//函数调用形式 }; myObject.double(); console.log(myObject.value) //3原因:当使用函数调用模式,this 被绑定到全局对象,即使是对象内部函数被调用时,this 仍然绑定到外部函数的 this 变量。这种设计的错误后果就是方法不能利用内部函数来帮助其工作,因为内部函数的 this 被绑定了错误的值。
解决方法: 该方法定义一个变量并给它赋值为 this, 则内部函数就可以通过那个变量访问到this。
var add = function(a, b) { return a + b; }; myObject.double = function() { var that = this; var helper = function() { this.value = add(this.value, this.value); console.log(this.value) //NaN console.log(that.value) //3 }; helper(); }; myObject.double(); console.log(myObject.value) //3 -
构造器调用模式
js 是一门基于原型继承的语言,这意味着对象可以直接从其他原型对象中继承属性。
如果在一个函数面前加 new 来调用,将会创建一个连接到该函数的 prototype成员的新对象,同时 this 也会绑定到那个新对象上。new前缀也会改变 return 语句的行为。
var Quo = function(string){ this.status = string; }; Quo.prototype.get_status = function(){ return this.status; }; var myQuo = new Quo("confused"); console.log(myQuo.get_status()); //confused -
Apply调用模式
apply方法让我们创建一个参数数组传递给调用函数,它可以选择 this 的值。apply 方法接受两个参数,第一个是要绑定给 this 的值,第二个就是一个参数数组。
var array = [3, 4]; var sum = add.apply(null, array); //sum的值为7 var statusObject = { status: 'A-OK' }; //虽然 statusObject并没有继承自Quo.prototype,但我们可以在statusObject上调用get_status方法。 var status = Quo.prototype.get_status.apply(statusObject); //status 的值为'A-OK'下面这道题是我在面试中遇到的,我不会的点还真的很多啊(下面的解答,大家直接去看原文就好了!
function fun(){ getName = function(){ console.log(1); } return this } fun.getName = function(){ console.log(2) } fun.prototype.getName = function(){ console.log(3) } var getName = function(){ console.log(4) } getName = function(){ console.log(5) } fun.getName() //2 getName()//5 fun().getName() //1 getName() //1 new fun.getName() //2 new fun().getName(); //3 (new fun()).getName() //3 (new fun).getName() //3 new new fun().getName() //3 -
var getName = function () { console.log('4'); }; function getName() { console.log(5); } getName(); //4点1:函数内部声明的getName 变量,前面是不带 var、let、const,声明的getName是全局范围内的。
function fun(){ getName = function(){ console.log(1); } return this }点二:var声明的变量和函数声明 function都会被提升,但是函数声明的提升的级别比 var 要高。 实际执行顺序如下:
function getName() { console.log(5); } var getName = function () { console.log('4'); }; getName(); //4点三: 操作符的优先级
fun().getName()()和.优先级相同,从左至右先执行 fun(),全局getName 被覆盖成输出console.log(1),并返回的this 此时代表的是window.随后相当于执行window.getName().
点四:还是前面的构造器调用模式,在函数前面加new调用,会创建一个函数prototype 成员的新对象,同时 this 会被绑定到那个对象上。
new fun.getName();.操作符的优先级要高于new,实际执行为
new (fun.getName)();new fun().getName();而上面的应该为
(new fun()).getName();new fun()创建一个函数prototype 成员的新对象,同时 this 会被绑定到那个对象上。在 prototype中找到 getName()方法。
new new fun().getName()第一步:(new (new fun().getName)() 第二步:(new ((new fun()).getName)()