JavaScript 是一种面向原型的语言。
它可以从构造函数构建实际对象,并且几乎具有任何对象可能具有的任何功能:
- 构造函数。
- 方法(即 JavaScript 中的函数)。
- 属性(从 ECMA-Script 5 开始,“getters/setters”)。
- 实例。
在 JavaScript 中,任何对象都有原型,包括函数。原型本身是将对象成员添加到整个对象的任何新创建实例的基本方法。
var constructor = function() { };
constructor.prototype.text = "hello world";
alert(new constructor().text); // This alerts hello world
为什么 JavaScript 不是面向对象的编程(脚本)语言?因为它没有符合面向对象编程定义要求的特性:
- 多态性:没有。您可以更改原型成员的行为,但这只是重用标识符。您无法访问伪派生对象中成员的先前实现。
- 继承:一点也不。也许原型链可以与继承相媲美,但 JavaScript(ECMA-Script 5.x 或更早版本)不像其他基于 OOP 的语言(即 Java、C#、Ruby、Python、VisualBasic.NET、... )。
- 封装。是的,当然,但是没有办法创建实际的私有或内部对象成员。
可能我忘了提一些其他的细节,但老实说,我相信这是一个很好的总结。
更新和总结
核心区别在于面向对象的编程语言具有面向对象范式必须具备的特征,才能被视为面向对象的编程语言。因此,就目前而言,JavaScript 并不是一种真正的面向对象编程语言,因为它缺乏真正的多态性和继承性。
更新:ES2015 及更高版本是否改变了这种情况?
从美学上讲是的,ES2015 及更高版本有一个重大改进,让我们考虑不完全但更接近面向对象的编程:调用超类的语法糖。
例如:
class A {
doStuff() {
console.log("hello world");
}
}
class B extends A {
doStuff() {
super.doStuff();
console.log("...and goodbye!");
}
}
这就是多态性。更专业的类可以覆盖其基类,以完全改变函数行为或执行基类已经在做的事情,向函数添加新代码。
顺便说一句,ES2015 及更高版本仍然缺乏真正的封装:访问修饰符 likeprivate
或public
here 在哪里? 无处。
而且,归根结底,ES2015 及更高版本实现了基于类的 OOP,但它仍然是 ECMAScript 5.x 之上的语法糖层......上面的代码仍然适用于引擎盖下的原型,并且工作方式相同就好像你会在 ECMAScript 5.x 中编写代码一样:
function A() {
}
A.prototype.doStuff = function() {
console.log("hello world");
};
function B() {
}
B.prototype = Object.create(A.prototype);
B.prototype.doStuff = function() {
A.prototype.doStuff.call(this);
console.log("...and goodbye!");
};
希望我需要再次更新这个答案,因为 ES2020 已经提出了访问修饰符,我们将能够考虑将 JavaScript 视为另一种完全支持面向对象编程的语言!