在不同的编程语言中,设计者也利用各种不同的语言特性来抽象描述对象,最为成功的流派是使用“类”的方式来描述对象,这诞生了诸如 C++、Java 等流行的编程语言。
而 JavaScript 早年却选择了一个更为冷门的方式:原型(关于原型,我在下一篇文章会重点介绍,这里你留个印象就可以了)。这是我在前面说它不合群的原因之一。
然而很不幸,因为一些公司政治原因,JavaScript 推出之时受管理层之命被要求模仿 Java,所以,JavaScript 创始人 Brendan Eich 在“原型运行时”的基础上引入了 new、this 等语言特性,使之“看起来更像 Java”。
JS 所使用的原型,是个什么样的存在啊?
如果我们从运行时角度来谈论对象,就是在讨论 JavaScript 实际运行中的模型,这是由于任何代码执行都必定绕不开运行时的对象模型。
不过,幸运的是,从运行时的角度看,可以不必受到这些“基于类的设施”的困扰,这是因为任何语言运行时类的概念都是被弱化的。
在我看来,不论我们使用什么样的编程语言,我们都先应该去理解对象的本质特征(参考 Grandy Booch《面向对象分析与设计》)。
“任何语言运行时类的概念都是被弱化的。” 这倒是有意思了
我们先来看第一个特征,对象具有唯一标识性。一般而言,各种语言的对象唯一标识性都是用内存地址来体现的, 对象具有唯一标识的内存地址,所以具有唯一的标识。
所以,JavaScript 程序员都知道,任何不同的 JavaScript 对象其实是互不相等的,我们可以看下面的代码,o1 和 o2 初看是两个一模一样的对象,但是打印出来的结果却是 false。
var o1 = { a: 1 };
var o2 = { a: 1 };
console.log(o1 == o2); // false
这倒是,iOS里面会通过特殊的手段,去判断2个对象的内容是否是一样的,但本质上,内容一致不代表对象是相等的。
关于对象的第二个和第三个特征“状态和行为”,不同语言会使用不同的术语来抽象描述它们,比如 C++ 中称它们为“成员变量”和“成员函数”,Java 中则称它们为“属性”和“方法”。
在 JavaScript 中,将状态和行为统一抽象为“属性”,考虑到 JavaScript 中将函数设计成一种特殊对象(关于这点,我会在后面的文章中详细讲解,此处先不用细究),所以 JavaScript 中的行为和状态都能用属性来抽象。
理解了函数式编程,这个倒是能理解,而且,也终于理解了下面这些 JS 代码
/// es6 可这样
var o = {
d: 1,
f() {
console.log(this.d);
}
};
/// 这个直接语法错误
var o = {
d: 1,
function f() {
console.log(this.d);
}
};
/// 古老的写法
var o = {
d: 1,
f: function() {
console.log(this.d);
}
};
从运行时的角度,介绍了 JavaScript 对象的具体设计:具有高度动态性的属性集合。
现在能理解这句话了