资讯专栏INFORMATION COLUMN

JavaScript中的原型与继承

ky0ncheng / 3443人阅读

摘要:如下代码示例删除删除方法每个对象中都会具有一个方法,该方法用来判断一个对象是否是一个对象的原型属性上述代码说明对象存在一个指向构造函数的原型,这个链接被叫做属性需要注意的是属性与属性并不等价。

原型

在JavaScript中,函数是一个包含属性和方法的Function类型的对象。而原型(Prototype)就是Function类型对象的一个属性
在函数定义时就包含prototype属性,它的初始值是一个空对象。在JavaScript中并没有定义函数的原型类型,所以原型可以是任何类型
原型是用于保存对象的共享属性和方法的,原型的属性和方法并不会影响函数本身的属性和方法

function foo(a,b){
    return a+b;
}
console.log(typeof foo.prototype);//object
获取原型

通过如下两种方式可以获取对象的原型,从而设置共享的属性和方法:

通过构造函数的prototype属性

function Person(){
    console.log("Person instantiated");
}
console.log(Person.prototype);

通过Object对象的getPrototypeOf(obj)方法

function Person(){
    console.log("Person instantiated");
}
console.log(Object.getPrototypeOf(Person));
原型的属性和方法

通过如下两种方式可以设置原型的属性和方法:

原型的属性和方法多带带进行定义

构造函数.prototype.属性名=属性值;
构造函数.prototype.方法名=function(){}

直接为原型定义一个新对象

构造函数.prototype={

属性名:属性值,
方法名:function(){}

}

自有属性与原型属性

自有属性:通过对象的引用添加的属性。其它对象可能无此属性;即使有,也是彼此独立的属性

原型属性:从原型对象中继承来的属性,一旦原型对象中属性值改变,所有继承自该原型的对象属性均改变

function Emp(ename,salary){
    this.ename=ename;
    this.salary=salary;
}
Emp.prototype={city:"北京市",dept:"研发部"}
var emp1=new Emp("Mary",3800);
var emp2=new Emp("Tom",3000);
检测自有或原型属性

使用hasOwnPrototype()方法检测对象是否具有指定的自有属性:

function Hero(){}
var hero=new Hero();
console.log(hero.hasOwnPrototype("name"));

使用in关键字检测对象及其原型链中是否具有指定属性:

function Hero(){}
var hero=new Hero();
console.log("name" in hero);
扩展属性或方法

通过原型可以为指定构造函数或对象扩展其属性或方法,如下代码示例:

function Hero(){}
Hero.prototype={
    name:"Mary",
    salary:3800
}

var hero=new Hero();
console.log(hero.name);//Mary
重写原型属性

通过构造函数或对象的自有属性可以重写原型的属性,如下代码示例:

function Hero(){}

Hero.prototype={
    name:"Mary",
    salary:3800
}

var hero=new Hero();
hero.name="Tom";

console.log(hero.name);//Tom
删除属性

通过delete关键字可以删除对象的属性,如果该对象既具有原型属性又具有自有属性的话,先删除自有属性,再删除原型属性。如下代码示例:

function Hero(){}
Hero.prototype={name:"Mary",salary:3800}

var hero=new Hero();
hero.name="Tom";

delete hero.name;//删除 Tom
console.log(hero.name);//Mary

delete hero.name;//删除 Mary
console.log(hero.name);//undefined
isPrototypeOf()方法

每个对象中都会具有一个isPrototypeOf()方法,该方法用来判断一个对象是否是一个对象的原型

var monkey={}
function Human(){}
Human.prototype=monkey;

var man=new Human();

monkey.isPrototypeOf(man);//true
__Proto__属性
function Hero(){}

Hero.prototype={
    name:"Mary",
    salary:3800
}

var hero=new Hero();
console.log(hero.name);//Mary

上述代码说明hero对象存在一个指向构造函数Hero的原型,这个链接被叫做__proto__属性
需要注意的是:__proto__属性与prototype属性并不等价。__proto__属性只能在调试时使用

__proto__属性是指定对象的属性

prototype属性是指定构造函数的属性

扩展内建对象

JavaScript中的内置对象有些也具有prototype属性,利用内置对象的prototype属性可以为内置对象扩展属性或方法
通过原型扩展内置对象的属性和方法非常灵活,根据个性化要求制定JavaScript语言的具体内容。一般建议慎用这种方式,如果JavaScript的版本更新时可能会提供个性化的属性或方法,导致冲突。

Array.prototype.inArray=function(color){
   for(var i=0,len=this.length;i
继承
原型链

构造函数或构造器具有prototype属性,对象具有__proto__属性,这就是之前学习的原型
如果构造函数或对象A,A的原型指向构造函数或对象B,B的原型再指向构造函数或对象C,以此类推,最终的构造函数或对象的原型指向Object的原型。由此形成一条链状结构,被称之为原型链。
按照上述的描述,在B中定义的属性或方法,可以直接在A中使用并不需要定义。这就是继承,它允许每个对象来访问其原型链上的任何属性或方法
原型链是ECMAScript标准中指定的默认实现继承的方式。

原型链实现继承
function A(){
    this.name="a";
    this.toString=function(){return this.name};
}
function B(){
    this.name="b";
}
function C(){
    this.name="c";
    this.age=18;
    this.getAge=function(){return this.age};
}
B.prototype=new A();
C.prototype=new B();
只继承于原型

出于对效率的考虑,尽可能地将属性和方法添加到原型上。可以采取以下方式:

不要为继承关系多带带创建新对象

尽量减少运行时的方法搜索

只继承于原型

根据上述方式进行更改后,代码如下:

function A(){}
A.prototype.name="a";
A.prototype.toString=function(){return this.name}

function B(){}
B.prototype=A.prototype;
B.prototype.name="b";

function C(){}
C.prototype=B.prototype;
C.prototype.name="c";
C.prototype.age=18;
C.prototype.getAge=function(){return this.age};

原型链虽然很强大,用它可以实现JavaScript中的继承,但同时也存在着一些问题。

原型链实际上是在多个构造函数或对象之间共享属性和方法

创建子类的对象时,不能像父级的构造函数传递任何参数

综上所述,在实际开发中很少会多带带使用原型链

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108266.html

相关文章

  • 理解JavaScript的核心知识点:原型

    摘要:首先,需要来理清一些基础的计算机编程概念编程哲学与设计模式计算机编程理念源自于对现实抽象的哲学思考,面向对象编程是其一种思维方式,与它并驾齐驱的是另外两种思路过程式和函数式编程。 JavaScript 中的原型机制一直以来都被众多开发者(包括本人)低估甚至忽视了,这是因为绝大多数人没有想要深刻理解这个机制的内涵,以及越来越多的开发者缺乏计算机编程相关的基础知识。对于这样的开发者来说 J...

    iKcamp 评论0 收藏0
  • 彻底理解Javascript中的原型继承

    摘要:在节中,我们学习到了通过构造函数创建对象的三个重要步骤,其中的一步是把构造函数的对象设置为创建对象的原型。利用而不是直接用创建一个实例对象的目的是,减少一次调用父构造函数的执行。 JavaScript语言不像面向对象的编程语言中有类的概念,所以也就没有类之间直接的继承,JavaScript中只有对象,使用函数模拟类,基于对象之间的原型链来实现继承关系,ES6的语法中新增了class关键...

    ziwenxie 评论0 收藏0
  • 彻底搞懂JavaScript中的继承

    摘要:这正是我们想要的太棒了毫不意外的,这种继承的方式被称为构造函数继承,在中是一种关键的实现的继承方法,相信你已经很好的掌握了。 你应该知道,JavaScript是一门基于原型链的语言,而我们今天的主题 -- 继承就和原型链这一概念息息相关。甚至可以说,所谓的原型链就是一条继承链。有些困惑了吗?接着看下去吧。 一、构造函数,原型属性与实例对象 要搞清楚如何在JavaScript中实现继承,...

    _ivan 评论0 收藏0
  • JavaScript中的继承

    摘要:前言作为中最重要的内容之一,继承问题一直是我们关注的重点。如果一个类别继承自另一个类别,就把这个称为的子类,而把称为的父类别也可以称是的超类。 前言 作为 JavaScript 中最重要的内容之一,继承问题一直是我们关注的重点。那么你是否清晰地知道它的原理以及各种实现方式呢 阅读这篇文章,你将知道: 什么是继承 实现继承有哪几种方式 它们各有什么特点 这里默认你已经清楚的知道构造函...

    guyan0319 评论0 收藏0
  • JavaScript系列--浅析原型继承

    摘要:综上所述有原型链继承,构造函数继承经典继承,组合继承,寄生继承,寄生组合继承五种方法,寄生组合式继承,集寄生式继承和组合继承的优点于一身是实现基于类型继承的最有效方法。 一、前言 继承是面向对象(OOP)语言中的一个最为人津津乐道的概念。许多面对对象(OOP)语言都支持两种继承方式::接口继承 和 实现继承 。 接口继承只继承方法签名,而实现继承则继承实际的方法。由于js中方法没有签名...

    draveness 评论0 收藏0
  • 你是否理解js的ObjectFunction原型

    摘要:原型对象是由创建的,因此原型对象的构造函数是构造函数也可以是称为对象,原型对象也就继承了其生父构造函数中的数据,也同时继承了原型对象的数据。当然这条原型链中的数据,会被还是还是这类构造函数继承,但是不会被这些继承,他们不处于同一个链条上。 js中,Function的本质是什么?Object的本质又是什么?js中有几条原型链? showImg(https://segmentfault.c...

    itvincent 评论0 收藏0

发表评论

0条评论

ky0ncheng

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<