这章内容我前后看了三次,感觉现在还没有完全吃透。而且让我感觉到Javascript的难度不次于C++,当然,这最主要的原因是:
Javascript和C++/Java不一样,它不是基于Class的OO语言,而是基于Prototype的OO。这个要求我们转变思维对待它,不过说来容易,做起来太难。(我蛮期待Javascript能够引入Class的概念,注意是这样的理念,不是这个关键字)。
为什么要这样呢,因为实际上现在Class的OO是主流,几乎所有围绕OO的设计编码方法都是围绕这个展开的(我知道很多人可能要跳出来说什么语言不是决定,关键是思想),我也很清楚Javascript可以模拟很多Class的OO,但是我还是强烈的希望直接支持它。
1. 定义一个Class
function MyClass(v) {
this.value = v;
}
这么三行语句,简单说它就是定义了一个函数,其它什么都不是。这个函数的名字是MyClass,参数是v。函数体是:
this.value = v; 就是这么多,多一点都没有。可是当这些东西和下面这个new放在一起的时候,奇迹发生了。
var mc = new MyClass(10);
奇迹是什么呢?
[1] 你可以访问到mc.value,并且结果会返回10;
[2] 你如果用 mc instanceof MyClass会返回true
[3] mc.constructor == MyClass也会返回true。
2. 定义方法,类方法(静态方法),类属性(静态属性)
所有的方法,或者说对象的方法,都是定义在prototype里的。而类方法和类属性都是直接定义成函数的属性的,如下:
MyClass.prototype.toString = function() {
return "[MyClass:" + this.value + "]";
}
MyClass.count = 0;
MyClass.max = function(a,b) {
if (a.value > b.value) {
return a;
} else {
return b;
}
}
3. 继承
继承的几个关键性质:
[1] 如果C继承自P,那么var c = new C(); c instanceof P应该是true;
[2] 如果C继承自P,那么如果C没有定义函数foo,但是P里面定义了,那么C应该默认有这个函数
[3] Override的功能。
<html>
<head>
<title>
</title>
</head>
<body>
<script language="javascript">
function Person(aName, aAge, aSex) {
this.name = aName;
this.age = aAge;
this.sex = aSex;
}
Person.prototype.toString = function() {
return "[Person " + this.name + " " + this.age
+ " " + this.sex +"]";
}
function Employee(aName, aAge, aSex, aID) {
this.superclass(aName, aAge, aSex);
this.id = aID;
}
Employee.prototype = new Person();
delete Employee.prototype.name;
delete Employee.prototype.age;
delete Employee.prototype.sex;
Employee.prototype.superclass = Person;
Employee.prototype.toString = function() {
return "[Employee " + this.id + " " + this.superclass.prototype.toString.call(this);
}
var p = new Person("AnkyHe", 28, "Male");
document.write(p + "<br>");
var e = new Employee("AnkyHe", 28, "Male", "90891234");
document.write(e + "<br>");
document.write("e instance of Person " + (e instanceof Person) + "<br>");
</script>
</body>
</html>
第22行代码就是为了实现要求[1][2](Employee.prototype = new Person(); )本质上就是为了使得Employee.prototype成为一个Person,然后所有定义在Person.prototype的方法(成员方法)都可以通过Employee.prototype访问到,也就是说成为Employee的成员方法。Override toString的时候,注意直接调用父类的方法。要用到apply或者call这种方法^_^
4. Mixni
这不是第一次听说这个概念了,最早是在Ruby里面。不过Ruby对Minxi的支持要强大一些,这个里面还要自己去定义一个borrow这样的函数。
<html>
<head>
<title>
</title>
</head>
<body>
<script language="javascript">
function borrow(from, to) {
for (var name in from.prototype) {
if (typeof from.prototype[name] != "function") {
continue;
}
to.prototype[name] = from.prototype[name];
}
}
function MixinToString() {}
MixinToString.prototype.toString = function() {
var rst = []
for (var name in this) {
if (!this.hasOwnProperty(name)) {
continue;
}
var value = this[name];
var s = name + ":";
switch(typeof value) {
case "function": s += "function"; break;
case "object":
{
if (value instanceof Array) {
s += "array";
} else {
s += value.toString();
}
break;
}
default: s += value.toString();
break;
}
rst.push(s);
}
return "{" + rst.join(", ") + "}";
}
function Book(aTitle, aAuthor, aPrice) {
this.title = aTitle;
this.author = aAuthor;
this.price = aPrice;
}
borrow(MixinToString, Book);
var book = new Book("Begin iPhone", "AnkyHe", 10);
document.write(book + "<br>");
</script>
</body>
</html>
本文深入探讨了JavaScript作为基于原型的面向对象语言的独特之处,包括如何定义类、方法、实现继承及混入等特性。通过具体实例展示了构造函数、原型链、继承机制的工作原理。

296

被折叠的 条评论
为什么被折叠?



