草庐IT

第一百一十八篇: JavaScript 原型链式继承

养肥胖虎 2023-03-28 原文

好家伙,好家伙,本篇为《JS高级程序设计》第八章“对象、类与面向对象编程”学习笔记

 

1.原型链

原型链是JS实现"继承"的方案之一

ECMA-262把原型链定义为ECMAScript的主要继承方式。其基本思想就是通过原型继承多个引用类型的属性和方法。

重温一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型。

如果原型是另一个类型的实例呢?那就意味着这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数。

这样就在实例和原型之间构造了一条原型链。这就是原型链的基本构想。

function SuperType() {
    this.property = true;
  }
  SuperType.prototype.getSuperValue = function() {
    return this.property;
  };
  function SubType() {
    this.subproperty = false;
  }
  // 继承SuperType
  SubType.prototype = new SuperType();
  SubType.prototype.getSubValue = function () {
    return this.subproperty;
  };
  let instance = new SubType();
  console.log(instance.getSuperValue()); // true

 

 

 

 

 

 

 

这个例子中实现继承的关键,是SubType没有使用默认原型,而是将其替换成了一个新的对象。

这个新的对象恰好是SuperType的实例。

这样一来,SubType的实例不仅能从SuperType的实例中继承属性和方法,而且还与SuperType的原型挂上了钩。

 

于是我们可以来看看他们的关系网

 

 

 

 实际上,原型链中还有一环。默认情况下,所有引用类型都继承自Object,这也是通过原型链实现的。完整的继承链

 

 

 

 

 

这样做有什么好处?

1.实现了继承

2.实例可以使用这个"链"上的所有内容,

特点:

1.就近原则,在读取实例上的属性时,首先会在实例上搜索这个属性。

如果没找到,则会继承搜索实例的原型。在通过原型链实现继承之后,搜索就可以继承向上,搜索原型的原型。

对属性和方法的搜索会一直持续到原型链的末端。

 

 

 

2.instanceof()方法和isPrototypeOf()方法

原型与实例的关系可以通过instanceof()方法和isPrototypeOf()方法来确定。

使用instanceof()方法检测实例的原型链中出现过相应的构造函数

使用isPrototypeOf()方法判断当前对象是否为另外一个对象的原型

function SuperType() {
    this.property = true;
}

function SubType() {
    this.subproperty = false;
}

// 继承SuperType
SubType.prototype = new SuperType();

let instance = new SubType();

console.log(instance instanceof Object);      
console.log(instance instanceof SuperType);   
console.log(instance instanceof SubType);     

console.log(Object.prototype.isPrototypeOf(instance));      
console.log(SuperType.prototype.isPrototypeOf(instance));  
console.log(SubType.prototype.isPrototypeOf(instance));     

 

 

 

 (全对✔)

 

 

 

3.方法覆盖

子类有时需要增加父类没有的方法 (不然为什么会需要子类...)

也可以进行方法覆盖

function SuperType() {
    this.property = true;
}
SuperType.prototype.getSuperValue = function () {
    return this.property;
};

function SubType() {
    this.subproperty = false;
}
// 继承SuperType
SubType.prototype = new SuperType();
//新方法
SubType.prototype.getSuperValue = function () {
    return this.subproperty;
};
//覆盖已有的方法
SubType.prototype.getSuperValue = function () {
    console.log("getSubValue()方法已被覆盖")
};

let instance = new SubType();

console.log(instance.getSuperValue()); // false

 

 

 

 

 

4.其它的继承方法

JavaScript继承(图解笔记) - 简书 (jianshu.com)

(写的挺好的,一篇直接看懂JS剩下的几种实现继承的方式)

 

有关第一百一十八篇: JavaScript 原型链式继承的更多相关文章

  1. ruby-on-rails - Rails 单表继承 : How to override the value written to the type field - 2

    在我的系统中,我已经定义了STI。Dog继承自Animal,在animals表中有一个type列,其值为"Dog"。现在我想让SpecialDog继承自dog,只是为了在某些特殊情况下稍微修改一下行为。数据还是一样。我需要通过SpecialDog运行的所有查询,以返回数据库中类型为Dog的值。我的问题是因为我有一个type列,rails将WHERE"animals"."type"IN('SpecialDog')附加到我的查询中,所以我不能获取原始的Dog条目。所以我想要的是以某种方式覆盖rails在通过SpecialDog访问数据库时使用的值,使其表现得像Dog。有没有办法覆盖用于类型

  2. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  3. ruby-on-rails - CarrierWave - PDF - 只选择第一页 - 2

    我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful

  4. ruby - 如何跳过 CSV 文件的第一行并将第二行作为标题 - 2

    有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|

  5. ruby-on-rails - 为什么 DataMapper 使用混合与继承? - 2

    所以我只是对此感到好奇:DataMapper为其模型使用混合classPostincludeDataMapper::Resource虽然active-record使用继承classPost有谁知道为什么DataMapper选择这样做(或者为什么AR选择不这样做)? 最佳答案 它允许您从另一个不是DM类的类继承。它还允许动态地将DM功能添加到类中。这是我正在处理的模块中的类方法:defdatamapper_classklass=self.dupklass.send(:include,DataMapper::Resource)klass

  6. arrays - 在一行中选择数组的第一个和最后一个元素 - 2

    我的任务是从数组中选择最高和最低的数字。我想我很清楚我想做什么,但只是努力以正确的格式访问信息以满足通过标准。defhigh_and_low(numbers)array=numbers.split("").map!{|x|x.to_i}array.sort!{|a,b|ba}putsarray[0,-1]end数字可能看起来像"80917234100",要通过,我需要输出"9234"。我正在尝试putsarray.first.last,但一直无法弄明白。 最佳答案 有Array#minmax完全满足您需要的方法:array=[80,

  7. ruby-on-rails - Ruby on Rails 单表继承(STI)和单元测试问题(使用 PostgreSQL) - 2

    我正在使用带有单个“帐户”表的STI模型来保存用户和技术人员的信息(即用户...8)错误:test_the_truth(用户测试):ActiveRecord::StatementInvalid:PGError:ERROR:关系“技术人员”不存在:从“技术人员”中删除...从本质上讲,标准框架不承认Technicians和Users表(或PostgreSQL称它们为“关系”)不存在,事实上,应该别名为Accounts。有什么想法吗?我对RoR比较陌生,不知道如何解决这个问题而又不完全删除STI。 最佳答案 原来问题是由于存在:./te

  8. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  9. ruby - 优雅的链式 'or' 用于测试 Ruby 中的相同变量 - 2

    怎样说才是明智的呢?if@thing=="01"or"02"or"03"or"04"or"05"(数字包含在数据类型字符串的列中。) 最佳答案 制作数组并使用.include?if["01","02","03","04","05"].include?(@thing)如果值真的都是连续的,你可以使用像(1..5).include?这样的范围对于字符串,你可以使用:if("01".."05").include?(@thing) 关于ruby-优雅的链式'or'用于测试Ruby中的相同变量,我

  10. ruby-on-rails - Ruby 或 Rails 有只将第一个字符大写的方法吗? - 2

    或者好像我必须自己写方法?(保持DHA不变):ruby-1.9.2-p180:001>s='omega-3(DHA)'=>"omega-3(DHA)"ruby-1.9.2-p180:002>s.capitalize=>"Omega-3(dha)"ruby-1.9.2-p180:003>s.titleize=>"Omega3(Dha)"ruby-1.9.2-p180:005>s[0].upcase+s[1..-1]=>"Omega-3(DHA)" 最佳答案 如果我的回答只是垃圾,我深表歉意(我不做ruby)。但我相信我已经为您找到了答

随机推荐