码迷,mamicode.com
首页 > 编程语言 > 详细

javascript继承分析

时间:2017-09-26 13:08:14      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:new   没有初始化   cal   coder   父类   一个   子类   func   构造   

一,传统JS继承方法:

  1,原型式继承:

    

//声明父类
function Person(name,age){   
    this.name = name;
    this.age = age;
    this.flag = true;
}
// 给父类添加方法
Person.prototype.sayName = function(){
    console.log(this.name);
}

//实例化父类
var person = new Person(zhl,30);
//调用父类方法
person.sayName();  // zhl

// 声明子类
function Worker(name,age,work){
    this.name = name;
    this.age = age;
    this.work = work;
}
//原型式继承  其实就是子类的原型指向父类的一个实例
Worker.prototype = new Person();
//给子类添加方法
Worker.prototype.sayWork = function(){
    console.log(this.work);
}

//实例化一个子类
var worker = new Worker(vsmart,32,itcoder);
//调用子类方法
worker.sayName();  // vsmart
worker.sayWork(); // itcoder

  貌似可以用了,不要高兴太早,这里是有很大的坑的!

  此继承方法有几个弊端:

  1,声明父类与子类的构造函数中有很多重复的初始化赋值;

  2,实例化子类的对象 flag 属性竟然是 true

    然而这个属性本身子类并没有初始化,哪来的?

    console.log(worker.flag) //true
    console.log(Worker.prototype.flag) //true

    哦,原来是从子类的原型上查找到的,也就是从父类的一个实例上获取到的;

    本来我们要做到 属性与方法分离的,现在呢,这个属性竟然在原型上,原型应该只放方法才对。

  3,子类的构造函数 constructor 竟然指向了 父类的 constructor,这个指向错误将来势必会带来耦合

    console.log(worker.constructor)  //

function Person(name,age){
    this.name = name;
    this.age = age;
    this.flag = true;
}

  综合以上几点我们要做优化;

  1,我们可以借用父类的构造函数初始化子类的构造函数  利用 apply 或 call 改变指向

  2,我们要重新改变子类的构造函数指向

  

//声明父类
function Person(name,age){   
    this.name = name;
    this.age = age;
    this.flag = true;
}
// 给父类添加方法
Person.prototype.sayName = function(){
    console.log(this.name);
}

//实例化父类
var person = new Person(‘zhl‘,30);
//调用父类方法
person.sayName();  // zhl

// 声明子类
function Worker(name,age,work){
    Person.apply(this,arguments);  // 借用父类构造方法
    this.work = work;
    this.flag = false;
}
//原型式继承  其实就是子类的原型指向父类的一个实例
Worker.prototype = new Person();
//给子类添加方法
Worker.prototype.sayWork = function(){
    console.log(this.work);
}
//改变constructor指向
Worker.prototype.constructor = Worker;

//实例化一个子类
var worker = new Worker(‘vsmart‘,32,‘itcoder‘);
//调用子类方法
worker.sayName();  // vsmart
worker.sayWork(); // itcoder

console.log(worker.flag) //false    //子类自己的属性
console.log(Worker.prototype.flag)  //true  从子类原型上查找
console.log(worker.constructor) //正确指向自己的构造方法

  function Worker(name,age,work){
    Person.apply(this,arguments);
    this.work = work;
    this.flag = false;
  }



   2,混合拷贝继承:

     所谓混合拷贝继承是指,构造函数还是借用父类的方式,但方法继承就是模拟拷贝的方式,

    

//声明父类
function Person(name,age){   
    this.name = name;
    this.age = age;
    this.flag = true;
}
// 给父类添加方法
Person.prototype.sayName = function(){
    console.log(this.name);
}

//实例化父类
var person = new Person(‘zhl‘,30);
//调用父类方法
//person.sayName();  // zhl

// 声明子类
function Worker(name,age,work){
    Person.apply(this,arguments);
    this.work = work;
    this.flag = false;
}
//原型式继承  其实就是子类的原型指向父类的一个实例
extends2(Worker.prototype,Person.prototype);
//给子类添加方法
Worker.prototype.sayWork = function(){
    console.log(this.work);
}
//拷贝继承核心方法
function extends2(child,parent){
    for(var attr in parent){
        if(parent.hasOwnProperty(attr)){
            child[attr] = parent[attr];
        }
    }
}

//实例化一个子类
var worker = new Worker(‘vsmart‘,32,‘itcoder‘);
//调用子类方法
worker.sayName();  // vsmart
worker.sayWork(); // itcoder

console.log(worker.flag) //false    //子类自己的属性
console.log(Worker.prototype.flag)  //false  子类原型上没有查找到
console.log(worker.constructor)   //
/*function Worker(name,age,work){
    Person.apply(this,arguments);
    this.work = work;
    this.flag = false;
}*/

 

  

    

javascript继承分析

标签:new   没有初始化   cal   coder   父类   一个   子类   func   构造   

原文地址:http://www.cnblogs.com/vsmart/p/7595869.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!