js--面向对象--原型链

本文详细介绍了JavaScript中面向对象的概念及实现方式,包括封装、原型链、构造函数继承、组合继承等不同继承模式的特点和应用。

js面向对象部分分为几个部分:
1.面向对象–封装
http://blog.youkuaiyun.com/github_34514750/article/details/51044272
2.本文介绍面向对象–原型链
3.面向对象–构造函数的继承
http://blog.youkuaiyun.com/github_34514750/article/details/51336839
4.本文介绍面向对象–非构造函数的继承
http://blog.youkuaiyun.com/github_34514750/article/details/51337015

1.回顾

回顾下构造函数,原型和实例的关系
构造函数:都有一个原型属性,指向一个原型对象。prototype
原型对象:都包含一个指向构造函数的指针.constructor
实例:包含一个指向原型对象的内部指针.[[prototype]]
http://blog.youkuaiyun.com/github_34514750/article/details/51044272#t1

2.原型链实现继承

ECMAScript无法实现接口继承,而是依靠原型链支持实现继承
基本思想:利用原型让一个引用类型继承另外一个引用类型的属性和方法。原型链的构建是将一个类型的实例赋值给另一个构造函数的原型实现的。从而,子类型可以访问超类型的所有属性和方法。
注意
通过原型链实现继承时,不能使用对象字面量创建原型方法,因为这样做就会重写原型链,随后导致无效。

<script type="text/javascript">  
    function Person(name,age){  
        this.name=name;  
        this.age=age;  
    }  
    Person.prototype.sayHello=function(){  
        alert("使用原型得到Name:"+this.name);  
    }  
    var per=new Person("wanghuan",22);  
    per.sayHello(); //输出:使用原型得到Name:wanghuan 

    function Student(){}  
    Student.prototype=new Person("shuguang",22);  
    Student.prototype.grade=5;  
    Student.prototype.intr=function(){  
        alert(this.grade);  
    }  
    var stu=new Student();  
    //stu指向Student的原型,Student原型又指向Person的原型
    stu.sayHello();//输出:使用原型得到Name:shuguang
    stu.intr();//输出:5  
</script>  

这里写图片描述
这里的原型链搜索机制
举例stu.sayHello();
1.先搜索实例中是否有sayHello()
2.搜索Student.prototype
3.搜索Person.prototype

问题:引用类型所有的原型属性会被实例共享,原型实现继承时,原型会变成另外一个类型的实例,则实例的属性则变成了现在的原型属性。从而被共享。举例:

function SuperType(){
    this.colors = ["red","blue","green"];
}
function SubType(){
}
//继承了SuperType
SubType.prototype = new SuperType();

var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);//red,blue,green,black

var instance2 = new SubType();
alert(instance2.colors);//red,blue,green,black

借用构造函数一起实现,即在子类型构造函数的内部调用超类型构造函数。
实例和原型之间,是通过内部指针[[prototype]]实现的,但是我们无法访问[[prototype]],则确定实例和原型的关系是通过instanceof和isPrototypeOf确定

注意:需要注意构造函数也有自己的proto,这点容易被自己忽略,如下所示

// 构造函数
function Foo(y) {
  // 构造函数将会以特定模式创建对象:被创建的对象都会有"y"属性
  this.y = y;
}

// "Foo.prototype"存放了新建对象的原型引用
// 所以我们可以将之用于定义继承和共享属性或方法
// 所以,和上例一样,我们有了如下代码:

// 继承属性"x"
Foo.prototype.x = 10;

// 继承方法"calculate"
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};

// 使用foo模式创建 "b" and "c"
var b = new Foo(20);
var c = new Foo(30);

// 调用继承的方法
b.calculate(30); // 60
c.calculate(40); // 80

// 让我们看看是否使用了预期的属性

console.log(

  b.__proto__ === Foo.prototype, // true
  c.__proto__ === Foo.prototype, // true

  // "Foo.prototype"自动创建了一个特殊的属性"constructor"
  // 指向a的构造函数本身
  // 实例"b"和"c"可以通过授权找到它并用以检测自己的构造函数

  b.constructor === Foo, // true
  c.constructor === Foo, // true
  Foo.prototype.constructor === Foo // true

  b.calculate === b.__proto__.calculate, // true
  b.__proto__.calculate === Foo.prototype.calculate // true

);

这里写图片描述
确定原型和实例之间的关系
instanceof:

alert(stu instanceof Object);
//true,所有引用类型默认都继承了Object,其实也是通过原型链实现的
alert(stu instanceof Student);//true
alert(stu instanceof Person);//true

isPrototypeOf():

alert(Object.prototype.isPrototypeOf(stu));//true
alert(Student.prototype.isPrototypeOf(stu));//true
alert(Person.prototype.isPrototypeOf(stu));//true

getPrototypeOf():

Object.getPrototypeOf(person1)==Person.prototye
3.借用构造函数实现继承

即子类型构造函数的内部调用超类型构造函数

function SuperType(){
    this.colors = ["red","blue","green"];
}
function SubType(){
    //继承了构造函数SuperType
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);//red,blue,green,black

var instance2 = new SubType();
alert(instance2.colors);//red,blue,green
function SuperType(){
    this.name = name;
}
function SubType(){
    //继承了构造函数SuperType,同时还传递了参数
    SuperType.call(this,"wanghuan");
    //实例属性
    this.age = 22;
}
var instance = new SubType();
alert(instance.name);//"wanghuan"
alert(instance.age);//22
4.组合继承(原型链和借用构造函数的技术组合)

优点
使用最多的继承模式就是组合继承,这种模式使用原型链继承共享的属性和方法,而且通过借用构造函数继承实例属性。

function SuperType(name){
    this.name = name;
    this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name,age){
    //继承属性
    SuperType.call(this,name);
    this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
};
//这种组合继承,可以使两个不同的SubType实例分别有各自的属性--包含colors属性,又可以使用相同的方法
var instance1 = new SubType("wanghuan","22");
instance1.colors.push("black");
alert(instance1.colors);//red,blue,green,black
instance1.sayName();//wanghuan
instance1.sayAge();//22

var instance2= new SubType("shuguang","23");
alert(instance2.colors);//red,blue,green
instance2.sayName();//shuguang
instance2.sayAge();//23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值