`
zccst
  • 浏览: 3292332 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[Object]继承(经典版)(二)原型链(原型继承)

阅读更多
作者:zccst

毫不夸张的说,这节是继承的核心所在。是重中之重。

一、原型链——将父类的实例赋给子类的prototype
function Person(name,age){
    this.name = name;
    this.age = age;
	this.arr = [11,22,33];
	this.alertName = "alertA";
    this.sayHi = function(){
        alert('hi');
    }
}

Person.prototype.walk = function(){
    alert('walk.......');
}

function Student(name,age,grade){   
    this.grade = grade;
}

Student.prototype = new Person();

var s1 = new Student('xiaoming',6,3);
/*
s1.walk();//walk.......
console.log(s1.name,s1.age,s1.grade);//undefined undefined 3
console.log(s1.constructor); // Person(name,age)
*/

var s2 = new Student('xiaowang',8,6);
console.log(s1.name,s1.age,s1.grade);
console.log(s2.name,s2.age,s2.grade);
s1.alertName = "alertB";
console.log(s1.alertName);
delete s1.alertName;
console.log(s1.alertName);
console.log(s2.alertName);
s1.arr.push(55);
console.log(s1.arr);
console.log(s2.arr);






Student.prototype.study = function(){
    alert('I am study');
}
var p1 = new Person();
//p1.study();// p1.study is not a function

缺点:虽然s1仍然指向父类的构造函数,但修改子类的共有方法并不会对父类有所影响,但是存在一个更为严重的问题是,子类没法继承父类的特权属性和特权方法。





二、原型链与call组合





三、原型继承的其他实现方式
1,直接将父类的prototype赋给子类的prototype
缺点:父类与子类耦合太高,因为改动了子类的prototype会影响父类。即使将原型对象的constructor指向子类构造函数,但子类和父类的实例都会共有相同的constructor,这种情形下修改子类的共有方法,同时会修改了父类的共有方法,说明此法不通。

function Person(name,age){
    this.name = name;
    this.age = age;
    this.sayHi = function(){
        alert('hi');
    }
}
Person.prototype.walk = function(){
    alert('walk.......');
}
function Student(name,age,grade){   //子类
    this.grade = grade;
}
Student.prototype = Person.prototype;

var s1 = new Student('xiaoming', 6, 3);
s1.walk();//walk.......
console.log(s1.name, s1.age, s1.grade);//undefined undefined 3
console.log(s1.constructor); // 就是Person构造函数 Person(name,age){...}

//主要缺陷:不能继承父类的特权属性和特权方法,子类的构造函数变成了Person(name,age),直接导致修改子类的原型方法时,父类也跟着修改了,耦合度太高了。
Student.prototype.study = function(){
    alert('I am study');
}
var p1 = new Person();
p1.study();//I am study





2, niubility方式-利用空函数实现继承 
优点:这种情况下修改Student的prototype就不会影响到Person的prototype对象了,并且,因为直接将Person的prototype赋给Empty的prototype,所以不会存在特权属性(实例属性)浪费资源的问题。这样利用空函数就能很好的解决共有方法的继承问题了。当然这时Student.prototype中的constructor是Person,所以最好加上Student.prototype.constructor = Student转换过来。

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.sayHi=function(){
	alert('hi');
}

function Student(name,age,grade){
    Person.call(this,name,age);
    this.grade = grade;
}

function Empty(){
}
Empty.prototype = Person.prototype;

Student.prototype = new Empty();
Student.prototype.constructor = Student;//特别关键的一句
Student.prototype.sayGrade=function(){
	alert(this.grade);
}

var p1 = new Person('xiaoming',10);
var s1 = new Student('xiaohong',9,3);
console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}
console.log(s1);//Student {name="xiaohong", age=9, grade=3, 更多...}
console.log(p1.constructor);//Person(name,age) 父类的实例指向仍是父类
console.log(s1.constructor);//Student(name,age,grade) //子类的实例指向仍是子类



//以下是错误的
Student.prototype.study = function(){
    alert('I am study');
}
var o1 = new Person();
o1.study();//错误
var e1 = new Empty();
e1.study();//错误







3,利用循环遍历拷贝的方法实现继承(循环将父类原型对象赋给子类原型对象)
for(var i in Person.prototype){
Student.prototype[i] = Person.prototype[i];
}
Student.prototype.constructor = Student;*/

优点:
父类原型对象的constructor指向父类构造函数,
子类原型对象的constructor指向子类构造函数,

这种循环方式,跟父类的实例属性和方法,没有任何关系,所以继承的实现用Call。

function Person(name,age){
	this.name = name;
	this.age  = age;
	this.sayName = function(){
		alert(this.name);
	};
}
Person.prototype.sayAge = function(){
	alert(this.age);
}

function Student(name,age,grade){
	Person.call(this, name, age);
	this.grade = grade;
}
//循环copy方式继承
for(var i in Person.prototype){
	alert(i);//只循环了一次,就是将父类原型方法sayAge赋给子类原型对象
    Student.prototype[i] = Person.prototype[i];
}
//批注:for in只循环自定义的prototype对象属性和方法,所以并不会修改constructor指针指向

//继续添加方法
Student.prototype.sayGrade = function(){
	alert(this.grade);
}

var s1 = new Student("zheng", 30, 3);
console.log(s1);
console.log(s1.constructor);
s1.sayGrade();

var p1 = new Person("aliali", 50);
console.log(p1);
console.log(p1.constructor);
//p1.sayGrade();

其实,父类和子类是没有任何关系的,唯一的联系是子类的prototype



如果您觉得本文的内容对您的学习有所帮助,您可以微信:
分享到:
评论

相关推荐

    终极原型链图示讲解.png

    终极原型链图示讲解 注1:原型对象是Object函数的实例对象,即,构造函数定义时,Object函数也创建了一个原型对象。且,构造函数的原型对象中有一个__proto__(隐式原型对象)指向Object的原型对象。 注2:Object函数...

    js 原型对象和原型链理解

    原型对象除了有原型属性外,为了实现继承,还有一个原型链指针__proto__,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用__proto__一直指向Object的原型对象上,而Object的原型对象用...

    js对象继承之原型链继承实例

    本文实例讲述了js对象继承之原型链继承的用法。分享给大家供大家参考。具体分析如下: 代码如下:[removed] //定义猫的对象 var kitty = {color:’yellow’,bark:function(){alert(‘喵喵’);},climb:...

    【JavaScript源代码】五句话帮你轻松搞定js原型链.docx

    作用:原型链的存在,主要是为了实现对象的继承。 一、 记住以下5句话,轻松搞定js原型链  Function 和 Object 都是构造函数 所有的构造函数都是Function new出来的(Function自己new了自己);所有的原型对象...

    Javascript原型链的原理详解

    ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。在JavaScript中,用 __proto__ 属性来表示一个对象的原型链。当查找一个...

    javascript基于原型链的继承及call和apply函数用法分析

    本文实例讲述了javascript基于原型链的继承及call和apply函数用法。分享给大家供大家参考,具体如下: 1. 继承是面向对象编程语言的一个重要特性,比如Java中,通过extend可以实现多继承,但是JavaScript中的继承...

    object c中关于继承代码示例

    object c中关于继承代码示例,代码

    JavaScript基于原型链的继承

    原型链是JavaScript中继承的主要方法。 原型链的基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法。 构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数...

    对于JS继承详细介绍( 原型链,构造函数,组合,原型式,寄生式,寄生组合,Class extends)

    说实在话,以前我只需要知道“寄生组合继承”是最好的,有个祖传代码...其中,原型链继承和原型式继承有一样的优缺点,构造函数继承与寄生式继承也相互对应。寄生组合继承基于Object.create, 同时优化了组合继承,成

    js原型链与继承解析(初体验)

    首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型是否与Object.prototype相等来证明是否存在obj的原型,答案返回true,所以存在。...

    JS原型链 详解及示例代码

    前言 在 segmentfault 上看到这样一道题目: ...在解题之前,先再说说 原型、原型链,以及 Function 和 Object 的关系,这也是本文的重点。 原型 在创建一个函数的时候,会自动为其创建一个原型对

    再谈javascript原型继承

    而由这个函数创建的对象也有一个__proto__属性指向这个原型,而函数的原型是一个对象,所以这个对象也会有一个__proto__指向自己的原型,这样逐层深入直到Object对象的原型,这样就形成了原型链。下面这张图很好的...

    学习javascript面向对象 理解javascript原型和原型链

    先看一张图,梳理梳理。 一、基本概念  【原型链】每个构造函数都有一个对象,原型...所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object的实例,因此默认原型都会包含

    javascript原型和原型链

    一、原型规则 1、所有的引用类型(数组、对象、函数)都具有对象特性,即可自由扩展属性(除了“null”) var array=[];array.a=1; var object={};object.a=1; function func(){}; func.a=1; 2、所有的引用类型...

    JavaScript原型及原型链终极详解

    JavaScript原型及原型链终极详解 一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object,Function 是JS自带的函数对象。下面举例说明 function f1(){}; var ...

    深入理解JS继承和原型链的问题

    对于那些熟悉基于类的面向对象语言(Java 或者 C++)的...这个原型对象又有自己的原型,直到某个对象的原型为null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototype

    浅谈javascript原型链与继承

    js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解。  首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型...

    几句话带你理解JS中的this、闭包、原型链

    原型链 所有对象都是基于Object.prototype,Object.prototype就是JavaScript的根对象,在Object.prototype中定义的方法都可以被其它对象访问到,当然也可以被重写了,所以直接在Object.prototype上调用的是原始功能...

Global site tag (gtag.js) - Google Analytics