本篇主要总结了this指针的指向问题。如果把问题细分,就可以更容易的得到判断。
以普通函数的方式调用(Invocation as a function)
1 | function test(){ |
结果是window。结论是当我们以一个函数的方式调用的时候,this就是指向window全局作用域。
定义在全局的函数, 函数的所有者就是当前页面, 也就是window对象。
我们可用通过函数名直接调用, 也可用通过window.方法名
来调用, 这个时候, 方法中的this关键字指向它的所有者:window对象.1
2
3
4
5function a() {
function b() { console.log(this); }
b();
}
a();
试试这一个,可能大家跟我一样,如果不仔细看,就会觉得结果是b。但实际上打印出来的还是window对象。
When invoked in this manner, the function context is the global context—the window object.
以对象方法来调用(Invocation as a method)
函数还可以作为某个对象的方法调用,这时this就指这个上级对象。1
2
3
4
5
6var obj = {
fun : function(){
console.log(this);
}
};
obj.fun();
结果是object。结论是当我们以一个对象的方法的形式来调用一个函数,这个时候的上下文就变成了这个对象,this指向的也就是这个对象。
When we invoke the function as the method of an object, that object becomes the function context and is available within the function via the this parameter.
以构造函数的形式(Invocation as a constructor)
通过构造函数可以生成一个新对象,this就指向这个新对象。1
2
3
4
5function creep(){
console.log(this);
return this;
}
new creep();
结果是creep{}。当我们以构造函数的形式唤醒一个函数的时候,就会发生下面这些事情:一个新的对象会首先被创建,被创建的对象会成为当前构造函数的上下文。
Invoking a function as a constructor is a powerful feature of JavaScript, because when a constructor is invoked, the following special actions take place:
* A new empty object is created.
* This object is passed to the constructor as the this parameter, and thus becomes the constructor’s function context.
* In the absence of any explicit return value, the new object is returned as the constructor's value.
Call和Apply改变this指向(Invocation with the apply() and call() methods)
apply(),Apply()是函数对象的一个方法,它的作用是改变函数的调用对象,切换函数执行的上下文环境(context),即 this 绑定的对象。
Call和Apply的区别在于,apply传递的是数组,call传递的是直接参数量。1
2
3
4
5
6
7
8
9
10
11
12
13function juggle() {
var result = 0;
for (var n = 0; n < arguments.length; n++) {
result += arguments[n];
}
this.result = result;
}
var ninja1 = {};
var ninja2 = {};
juggle.apply(ninja1,[1,2,3,4]);
juggle.call(ninja2,5,6,7,8);
assert(ninja1.result === 10,"juggled via apply");
assert(ninja2.result === 26,"juggled via call");
To invoke a function using its apply() method, we pass two parameters to apply(): the object to be used as the function context, and an array of values to be used as the invocation arguments. The call() method is used in a similar manner, except that the arguments are passed directly in the argument list rather than as an array.
以事件处理函数的方式
1 | function test(){ |
这样是可以准确的得到input里面的值的,但是为啥这里this不是window对象呢?test是再全局作用域下定义的吗?为啥可以成功的获取到DOM的值呢?
问题出在onclick事件绑定的时候,在对onclick绑定处理器的时候, 其实是对id为name的输入框Dom对象的onclick属性赋值。
比如说我们把这个onblur对象打印出来:console.log(document.getElementById(“ele”).onblur);
可以看到这个onblur底下是有test函数的。
比如说下面这个可以得到正确的答案吗?1
2
3
4function test() {
alert(this.value);
}
<input id="name" type="text" value="test" onclick="test()"/>
这个时候的alert出来的是undefined。所以这里的this指向全局对象window。
嵌套函数中的this
嵌套函数中的this不会继承父级函数的this,需要将this变量进行暂存,保存到另外一个变量中才行。比如下面一个例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28//例子1
var name = "outer";
var foo3 = {
name: "inner",
sayHello: function() {
console.log(this.name);
var subSayHello = function() {
console.log(this.name);
}
subSayHello();
}
}
foo3.sayHello(); //先输出inner,后输出outer
//例子2
var name = "outer";
var foo3 = {
name: "inner",
sayHello: function() {
var that = this;
console.log(that.name);
var subSayHello = function() {
console.log(that.name);
}
subSayHello();
}
}
foo3.sayHello(); // 都输出inner
严格模式下的this
ECMAScript 5 引入了 strict mode ,现在已经被大多浏览器实现(包括IE10. 会使web浏览器更容易的解析代码(只需要添加 “use strict”; 在源码的最上面), 由现有的代码到严格模式的过渡需要一些事做.
在普通的函数调用f()中,this的值会指向全局对象.在严格模式中,this的值会指向undefined.
当函数通过call和apply调用时,如果传入的thisvalue参数是一个null和undefined除外的原始值(字符串,数字,布尔值),则this的值会成为那个原始值对应的包装对象,如果thisvalue参数的值是undefined或null,则this的值会指向全局对象.在严格模式中,this的值就是thisvalue参数的值,没有任何类型转换.
总结
问题来啦,调用者是谁this就指向谁,这句话对吗???!!!