this、call和apply
this
this指向一个对象,具体指向是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。
this的指向
1.作为对象的方法调用
当函数作为对象的方法被调用时,this指向该对象
var obj = {
a: 1,
getA: function() {
alert(this===obj); //输出:true
alert(this.a); //输出: 1
}
};
obj.getA();
2.作为普通函数调用
this总指向全局对象,注意在严格模式下是undefined
window.id = 'window';
document.getElementById('div1').onclick = function() {
alert(this.id); //输出: 'div1'
var callback = function () {
alert(this.id); //输出: 'window'
}
callback();
}
此时有一种简单的解决方案,可以创建一个变量保存div节点引用
var that = this;
3.构造器调用
构造器跟普通函数的区别在于被调用的方式。当用new调用函数时,该函数总是返回一个对象,this就指向该对象。
var MyClass = function () {
this.name = 'sven';
};
var obj = new MyClass();
alert(obj.name); //输出: sven
需要注意的是:如果构造器显式的返回一个object类型的对象,那么此次运算结果最终会返回这个对象
var MyClass = function () {
this.name = 'sven';
return { //显示返回一个对象
name: 'anne'
}
};
var obj = new MyClass();
alert(obj.name); //输出: anne
4.Function.prototype.call和Function.prototype.apply调用
可以动态的改变传入函数的this
var obj1 = {
name: 'sven',
getName: function() {
return this.name;
}
};
var obj2 = {
name: 'anne'
};
console.log(obj1.getName()); //输出: sven
console.log(obj1.getName.call(obj2)); //输出: anne
call和apply
区别
都是非常有用的方法,作用一模一样,区别仅在于传入参数形式的不同。
apply第一个参数指定了函数体this对象的指向,第二个参数为数组。
call第一个一样,第二个参数开始往后,每个参数依次传入函数。
用途
1.改变this指向
将上述this指向第二点的callback()改成callback.this(this)也可以让this指向div1.
2.Function.prototype.bind
bind用来指定函数内部的this指向。 可以用apply来模拟一个bind
3.借用其他对象的方法
借用构造函数,实现一些类似继承效果。
var A = function() {
this.name = name;
};
var B = function() {
A.apply(this, arguments);
};
B.prototype.getName = function() {
return this.name;
};
var b = new B('sven');
console.log(b.getName()); //输出: sven
第二种运用场景:函数的参数列表是一个类数组对象,但并非真正的数组,也不能像数组一样进行排序、添加元素,这种情况下常常借用Array.prototype对象上的方法,比如Array.prototype.push.
(function() {
Array.prototype.push.call(arguments, 3);
console.log(arguments); //输出[1,2,3]
})(1,2);
我们可以把“任意”对象传入Array.prototype.push只要满足以下两个条件:
var a = {};
Array.prototype.push.call(a, 'first');
alert(a.length); //输出:1
alert(a[0]); //输出: first
1)对象本身要可以存取属性。比如a为number类型就不行
2)对象的length属性可读写。函数的length属性就是一个只读的属性。