Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript中的多态 #4

Open
lovelmh13 opened this issue Jul 15, 2019 · 0 comments
Open

JavaScript中的多态 #4

lovelmh13 opened this issue Jul 15, 2019 · 0 comments

Comments

@lovelmh13
Copy link
Owner

lovelmh13 commented Jul 15, 2019

JavaScript中的多态

开始初学JavaScript时,听说JavaScript没有多态,我就天真的以为JavaScript真的没有。那么,JavaScript真的没有多态吗?

多态是什么

多态是同一个行为具有多个不同表现形式或形态的能力。

多态就是同一个接口,使用不同的实例而执行不同操作

听起来是不是像是if else或者switch case ?

对,使用多态可以取代这些过程化的条件语句,使代码间解耦。

之前面试被问过哪些方法可以使一个函数有多种执行结果,只回答出了条件语句,现在想想,如果当时了解了多态,应该可以加一点分把。

多态的体现1

有这样一段代码:

let WangYiYun = {
    play: function () {
        console.log('网易云音乐');
    }
};
let QQMusic = {
	play: function () {
        console.log('QQ音乐');
    }
};

function putOnsomeMusic (musicPlayer) {
	if (musicPlayer === 'wangYiYun') {
		WangYiYun.play();
    } else if (musicPlayer === 'QQMusic') {
        QQMusic.play();
	}
}

上面的代码,如果我们想添加第三种播放器—酷狗音乐,就需要再改写putOnsomeMusic,判断是酷狗的话,执行酷狗的播放。

这种改动是有一定的风险的,我们应该遵循开闭原则:对扩展是开放的,对修改是关闭的。

我们找出代码中的多态性,尝试改写一下上面的代码:

function putOnsomeMusic (musicPlayer) {
	if (musicPlayer.play instanceof Function) {
        musicPlayer.play();
	}
}
putOnsomeMusic(WangYiYun);
putOnsomeMusic(QQMusic);

现在,如果再加其他的播放器,我们只需要定义好,然后把参数传进去。(假设所有播放器都是play()方法来播放)

做到多态,我们就需要把代码抽象,分离,解耦。把“做什么”和“谁去做”,分离开。

多态最根本的作用就是通过把过程化的条件分支语句转化为对象的多态性,从而消除这些条件分支语句。

多态的体现2:重写

这里直接复制了《你不知道的JavaScript》里的例子

function mixin( sourceObj, targetObj ) {
	for (var key in sourceObj) {
	// 只会在不存在的情况下复制
		if (!(key in targetObj)) {
			targetObj[key] = sourceObj[key];
		}
	}
	return targetObj;
}
var Vehicle = {
	engines: 1,
	ignition: function() {
		console.log( "Turning on my engine." );
	},
	drive: function() {
		this.ignition();
		console.log( "Steering and moving forward!" );
	}
};
var Car = mixin( Vehicle, {
	wheels: 4,
	drive: function() {
		Vehicle.drive.call( this );
		console.log("Rolling on all " + this.wheels + " wheels!");
	}
});
Vehicle.drive();
// Turning on my engine.
// Steering and moving forward!
Car.drive();
// Turning on my engine.
// Steering and moving forward! 
// Rolling on all 4 wheels!

可以看出来,在Car中,我们重写了Vehicle的方法。

我们来分析一下这条语句: Vehicle.drive.call( this )。 这就是显式多态。

由于 Car 和 Vehicle 中都有 drive() 函数, 为了指明调用对象, 我们必须使用绝对( 而不是相对) 引 用。 我们通过名称显式指定 Vehicle 对象并调用它的 drive() 函数。

但是如果直接执行 Vehicle.drive(), 函数调用中的 this 会被绑定到 Vehicle 对象而不是 Car 对象, 这并不是我们想要的。 因此, 我们会使用 .call(this) 来确保 drive() 在 Car 对象的上下文中执行。

总结

开始看到这两种都是多态的时候,我是有些懵逼的。后来想了想,也没什么不对。

不管是抽象,还是重写,都是为了让一段代码,有了不同的表现形式。可以做出不同的事儿。

参考文章:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant