优雅地实现JavaScript的继承

众所周知,面向对象编程有三个重要的概念: 封装、继承、多态。而JS作为面向对象的弱类型语言,应该说是基于对象的语言,正如常说的,JS的世界里,万物皆对象。虽然JS本身不是面向对象的语言,我们可以通过模拟的方法,来实现类似JAVA式的类继承。

1、创建一个自定义对象

//构造函数
function People(name,age){
    this.name = name;
    this.age = age;
}
//定义原型对象
People.peototype={
    getName : function(){
        return this.name;
    },
    getAge : function(){
        return this.age;
    }
}var p1 = new People(‘leaf‘,10);console.log(p1.getName())  //leaf

2、当执行 var p1 = new People(‘leaf‘,10);内部主要做了这几件事   

1. 创建新的空对象(new Object());

2. 设置新对象的__proto__继承构造函数的prototype (p1.__proto__===People.prototype );            

3. 将这个对象通过this关键字传递到构造函数中并执行构造函数。

4. 将这个对象赋值给p1.

3、简单的继承,看看

创建student类,它从People继承了原型prototype中所有的属性。

function Student(name, age, score) {
    this.name = name;
    this.age = age;
    this.score = score;
}
// 将Studen原型指向Person的一个实例(其实就是Student.prototype里的__proto__指向了People的实例中的__proto__,而People的实例中的__proto__又指向了People.prototype)。因为People的实例可以调用People原型中的方法, 所以Studen的实例也可以调用Person原型中的所有属性。
Studen.prototype = new Person();
Student.prototype.constructor = Student;  //避免实例的constructor属性指向Object函数
Studen.prototype.getScore= function() { return this.score; }; var p1 = new Employee("leaf", "12", "100"); console.log(p1.getName()); // "leaf  

4、3中的方法存在的问题

1、在创建Student构造函数和原型时,就对Pelple进行了实例化,这是不合适的。
   2、Student的构造函数没法调用父类Person的构造函数,导致在People构造函数中对name和age属性的重复赋值。
   3、Student中的函数会覆盖Pelple中的同名函数,没有重载的机制.

5、修复之后更加优雅地继承

//构造函数
function People(name,age){
    this.name = name;
    this.age = age;
}
//定义原型对象
People.prototype={
    constructor : People,
    getName : function(){
        return this.name;
    },
    getAge : function(){
        return this.age;
    }
}

//定义一个Student类
function Student(name,age,score){
    //调用Peopel构造函数,this指向了People
    People.apply(this,arguments);
    this.score=score;
}

Student.prototype = {
    constructor :Student,
    getScore:function(){
       return this.score;
    }
}

//让Student的原型对象继承People的原型对象Object.setPrototypeOf(
    Student.prototype, People.prototype
);

var p2 = new Student(‘kafu‘,10,99);console.log(p2.getScore());//99console.log(p2.getName()); //kafuconsole.log(Student.prototype.constructor==Student); //true、

  

6、总结

主要利用两点

1、在子类型构造函数中调用父类型构造函数,改变this的指向。

注意:可以使用call(this,参数属性)、apply(this,[参数数组])

2、利用Object.setPrototypeOf()
注意:该方法的Polyfill

Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
  obj.__proto__ = proto;
  return obj;
}

  

时间: 2024-08-01 22:46:28

优雅地实现JavaScript的继承的相关文章

javascript类继承

function extend(subClass, superClass) { var f = function() {}; f.prototype = superClass.prototype; subClass.prototype = new f(); subClass.superClass = superClass.prototype; } var parent = function (name, age) { this._name = name; this._age = age; };

javascript深度克隆与javascript的继承实现

1.javascript深度克隆: //注意这里的对象包括object和array function cloneObject(obj){ var o = obj.constructor === Array ? [] : {}; for(var key in obj){ if(obj.hasOwnProperty(key)){ o[key] = typeof obj[key] === "object" ? cloneObject(obj[key]) : obj[key]; } } ret

JavaScript原型继承的陷阱

JavaScript原型继承的陷阱 JavaScript默认采用原型继承.虽然没有类(class)的概念,它的函数(function)可以充当构造器(constructor).构造器结合this,new可以构建出类似Java的类.因此,JavaScript通过扩展自身能模拟类式(class-based)继承. JavaScript和其它面向对象语言一样,对象类型采用引用方式.持有对象的变量只是一个地址,而基本类型数据是值.当原型上存储对象时,就可能有一些陷阱. 先看第一个例子 var creat

浅话javascript的继承

javascript的继承和java或C#的继承是不一样的,后者是基于类的继承,而javascript是通过原型来继承的.所以,先得理一理原型是个什么鬼. 当一个函数对象被创建时,Function构造器产生的函数对象会运行类似这样一些代码:this.prototype={constructor:this},新对象被赋予prototype这样一个属性,它的值是一个包含constructor属性的对象.可以看出,这个constructor指向新对象本身.prototype属性指向的对象自然不会只有c

[JavaScript原型继承理解一]

转:http://www.cnblogs.com/harolei/p/3740354.html 对于JavaScript的继承和原型链,虽然之前自己看了书也听了session,但还是一直觉得云里雾里,不禁感叹JavaScript真是一门神奇的语言.这次经过Sponsor的一对一辅导和自己回来后反复思考,总算觉得把其中的精妙领悟一二了. 1. JavaScript创建对象 在面向对象语言中,通常通过定义类然后再进行实例化来创建多个具有相同属性和方法的对象.但是在JavaScript中并没有类的概念

[ JavaScript ] JavaScript 实现继承.

对于javascript中的继承,由于js中没有后端语言中的类式继承,所以js中的继承,一般都是原型继承(prototype). function P (name){ this.name = name; this.say = function(){ console.log('p'); } } function S (name,id){ this.id = id; this.eat = function(){ console.log('s'); } } S.prototype = P.protot

JavaScript组合继承的一点思考

今天看<JavaScript高级程序设计>一书中关于组合继承模式时,书上有这么一个Demo程序: <html> <head> </head> <body> <script> function SuperType(name){ this.name = name; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name,

Javascript 进阶 继承

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/29194261 1.基于类的继承 下面看下面的代码: <script type="text/javascript"> function Person(name, age) { this.name = name; this.age = age; } Person.prototype.say = function () { console.log(this.na

javascript实现继承的方式

this this表示当前对象,如果在全局作用范围内使用this,则指代当前页面对象window: 如果在函数中使用this,则this指代什么是根据运行时此函数在什么对象上被调用. 我们还可以使用apply和call两个全局方法来改变函数中this的具体指向. 先看一个在全局作用范围内使用this的例子: <script type="text/javascript"> console.log(this === window);  // true console.log(w