javascript 的 this 总是指向一个对象,且指向的对象 基于函数的执行环境 动态绑定,而不是函数声明时的环境
函数 getNum 作为对象 obj 的方法被调用,this 指向对象 obj
var obj = {
numb: 1,
getNum: function(){
alert(this === obj) // -> true
alert(this.num) // -> 1
}
}
此时 this 总是指向全局对象,在浏览器中,这个全局对象就是 window
window.name = 'global'
var getName = function() {
return this.name
}
getName() // 返回 global
这时就会遇到一个我们不想要的情况:
window.name = 'global'
var obj = {
name: 'sven',
getName: function(){
return this.name;
}
}
var getNameGlobal = obj.getName
alert(getNameGlobal()) // 输出 global
我们可以通过设置一个变量来解决 (这部分内容存疑,但在代码行中是可实现的):
window.name = 'global'
var obj = {
name: 'sven',
that: this,
getName: function() {
return that.name;
}
}
javascript 中没有类,但可以通过 new 运算符来从函数中构造对象:
var myClass = function(){
this.name = 'sven'
}
var obj = new myClass();
alert(obj.name) // sven
不过需要注意的是,如果 function 显式返回一个对象,运算结果还是那个返回值
var myClass = function() {
this.name = 'sven'
return {
name: 'anne'
}
}
var obj = new myClass()
alert(obj.name) // anne
用 call 和 apply 可以动态地改变传入函数的 this:
var obj = {
name: 'sven'
getName: function(){
return this.name;
}
}
var obj2 = { name: 'anne' }
alert(obj1.getName.call(obj2)) // anne
call 和 apply 作用一模一样,只是传入参数的形式不同
var func = function(a, b, c){
alert([a, b, c])
}
func.apply(null, [1, 2, 3]) // 参数以数组的形式发送,用的更多~
func.call(null, 1, 2, 3) // 参数一个一个传入
那么在 javascript 中 call 和 apply 有什么实际用途?
document.getElementById('div1').onclick = function(){
alert(this.id)
var func = function(){
alert(this.id)
}
func() // window.id => undefined
func.call(this) // div1
}
Function.prototype.bind = function(ctx) {
var self = this;
return function(){
return self.apply(ctx, arguments);
}
}
var obj = { name: 'sven' }
var func = function(){
alert(this.name)
}.bind(obj)
func(); // 输出 sven
如下这样,就可以通过借用其他构造函数来实现类似继承的效果了:
var A = function (name) {
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());
另一个例子是借用一些实用类,这就使得一些本来不是数组的东西也可以使用数组的方法了:
(function () {
var x = Array.prototype.push.apply(arguments, [4, 5, 6]);
console.log(arguments);
})(1, 2, 3); // 添加新元素
(function () {
var x = Array.prototype.slice.apply(arguments, [0, 1]);
console.log(x);
})(1, 2, 3, 4, 5); // 转换成真的数组