一直对JS的继承概念有点模糊, 大体知道是怎么回事, 但也没有去深究过, 今天翻阅【JavaScript语言精髓】一书的第五章比较深刻进行认知, 特此记录一番。
JavaScript是一门基于原型的语言, 其对象是直接从其他对象继承的
var Person = function(name){
this.name = name;
}
Person.prototype.whoAmI = function(){
console.info(this.name);
}
var Student = function(grade){
this.grade = grade;
}
Student.prototype = new Person('haolin');
Function.prototype.method = function(name, func){
this.prototype[name] = func;
return this;
}
上述代码片段, 为Function.prototype增加一个method方法, 这样我们就可以通过String.method("newMethod", function(){...}) (而不是String.prototype.newMethod = function(){...})来为String扩展新方法了。
Function.method("extends", function(Parent){
this.prototype = new Parent;
return this;
});
var Student = function(grade){
this.grade = grade;
}.extends(Person);
现在我们基本达到了继承的目的, 但是也存在一些问题, 比如父类属性能公开访问, 在继承时需要加上new关键字等。
var constructor = function(spec, my){
var that, 其他私有实例变量
my = my || {};
把共享的变量和函数添加到my中
that = 一个新对象
添加给that访问私有属性的方法
return that;
}
var person = function(context){
var that = {};
var whoAmI = function(){
return context.name;
};
that.whoAmI = whoAmI;
var howOld = function(){
return context.age || 0;
};
that.howOld = howOld;
return that;
}
var p2 = person({"name" : "haolin", "age" : 24});
var student = function(context){
var number = context.number || "";
// 调用父类构造方法, 并能访问父类暴露的接口whoAmI, howOld
var that = person(context);
// 子类扩展方法
var getNumber = function(){
return number;
}
that.getNumber = getNumber;
var selfIntroduce = function(){
return "I am " + that.whoAmI() + ", I'm " + that.howOld() + " years old, My number is " + number;
}
that.selfIntroduce = selfIntroduce;
return that;
}
var s2 = student({"name" : "haolin", "age" : 24, "number" : "123456"});
现在的前端项目都使用CoffeeScript, 其支持类和继承, 想看看它是怎么理解JS的类和继承的。
class Person
constructor: (@name, @age) ->
getName: ->
console.info @name
class Student extends Person
constructor: (@number) ->
getNumber: ->
console.info @number
var Person, Student, __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { //扩展函数
for (var key in parent) {
if (__hasProp.call(parent, key)) //赋值父类属性
child[key] = parent[key];
}
function ctor() { //子类构造函数
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype; //父类标识
return child;
};
Person = (function() { //使用闭包, 保护属性
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = function() {
return console.info(this.name);
};
return Person;
})(); //发起一次调用
Student = (function(_super) {
__extends(Student, _super);
function Student(number) {
this.number = number;
}
Student.prototype.getNumber = function() {
return console.info(this.number);
};
return Student;
})(Person);