JavaScript 设计模式中的 this、call 和 apply(设计模式与开发实践 P3)

本文聚焦JavaScript,介绍了this和call、apply的相关知识。this总是指向一个对象,其指向基于函数执行环境动态绑定。call和apply作用相同但传参形式不同,可用于修正函数中的this、模拟bind函数、借用其他对象的方法,还能实现类似继承的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.1 this

javascript 的 this 总是指向一个对象,且指向的对象 基于函数的执行环境 动态绑定,而不是函数声明时的环境

this 作为对象的方法

函数 getNum 作为对象 obj 的方法被调用,this 指向对象 obj

var obj = {
	numb: 1,
	getNum: function(){
		alert(this === obj) // -> true
		alert(this.num) // -> 1
	}
}

this 作为普通函数

此时 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

用 call 和 apply 可以动态地改变传入函数的 this:

var obj = {
	name: 'sven'
	getName: function(){
		return this.name;
	}
}

var obj2 = { name: 'anne' }

alert(obj1.getName.call(obj2)) // anne

2.2 call 和 apply

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 有什么实际用途?

修正函数中的 this

document.getElementById('div1').onclick = function(){
	alert(this.id)
	var func = function(){
		alert(this.id)
	}
	func() // window.id => undefined
	func.call(this) // div1
}

模拟 bind 函数

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); // 转换成真的数组
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值