原型与原型链详解

与大部分面向对象语言不同,ES6之前中并没有引入类(class)的概念,JavaScript并非通过类而是直接通过构造函数来创建实例。在介绍原型和原型链之前,我们有必要先复习一下构造函数的知识。

构造函数模式的目的就是为了创建一个自定义类,并且创建这个类的实例。构造函数模式中拥有了类和实例的概念,并且实例和实例之间是相互独立的,即实例识别。

构造函数就是一个普通的函数,创建方式和普通函数没有区别, 不同的是构造函数习惯上首字母大写 。另外就是调用方式的不同,普通函数是直接调用, 而构造函数需要使用new关键字来调用

每创建一个Person构造函数,在Person构造函数中,为每一个对象都添加了一个sayName方法,也就是说构造函数每执行一次就会创建一个新的sayName方法。这样就导致了构造函数执行一次就会创建一个新的方法,执行10000次就会创建10000个新的方法,而10000个方法都是一摸一样的,为什么不把这个方法单独放到一个地方,并让所有的实例都可以访问到呢?这就需要原型( prototype )

在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个 prototype 属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。

让我们用一张图表示构造函数和实例原型之间的关系:

原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。

每一个对象数据类型(普通的对象、实例、 prototype ......)也天生自带一个属性 __proto__ ,属性值是当前实例所属类的原型( prototype )。原型对象中有一个属性 constructor , 它指向函数对象。

在JavaScript中万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链

举例说明:person → Person → Object ,普通人继承人类,人类继承对象类

当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined。

我们可以使用对象的 hasOwnProperty() 来检查对象自身中是否含有该属性;使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true

person实例中没有a这个属性,从 person 对象中找不到 a 属性就会从 person 的原型也就是 person.__proto__ ,也就是 Person.prototype中查找,很幸运地得到a的值为123。那假如 person.__proto__ 中也没有该属性,又该如何查找?

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。 Object是JS中所有对象数据类型的基类(最顶层的类)在Object.prototype上没有 __proto__ 这个属性。



  • 鍘熷瀷鍜屽師鍨嬮摼鏄粈涔?
    绛旓細鍘熷瀷鍜屽師鍨嬮摼鏄敤绾挎潯鍥惧舰鎻忕粯鍑虹殑浜у搧妗嗘灦锛屼篃绉扮嚎妗嗗浘銆傚師鍨嬮摼閫氫織鏄撴噦鐨勭悊瑙e氨鏄彲浠ユ妸瀹冩兂璞℃垚涓涓摼鏉★紝浜掔浉杩炴帴鏋勬垚涓鏁翠覆閾惧瓙锛岃屽師鍨嬮摼涓氨鏄疄渚嬪璞″拰鍘熷瀷瀵硅薄涔嬮棿鐨勯摼鎺ワ紝姣忎釜鍑芥暟閮芥湁涓涓猵rototype灞炴э紝杩欎釜prototype灞炴у氨鏄垜浠殑鍘熷瀷瀵硅薄銆傚師鍨嬮摼鐨勭壒鐐 鍘熷瀷閾鹃氳繃闅愬紡鍘熷瀷鎶婁竴浜涙瀯閫犲嚱鏁板眰...
  • 鍘熷瀷鍜屽師鍨嬮摼鐨勭悊瑙
    绛旓細閭d箞鏄庣櫧浜嗕笁鑰呬箣闂寸殑鍏崇郴鎴戜滑灏辨潵璇翠竴涓鍘熷瀷閾锛屼粠涓涓疄渚嬪璞″悜涓婃壘鏈変竴涓瀯閫犲疄渚嬬殑鍘熷瀷瀵硅薄锛岃繖涓師鍨嬪璞″張鏈夋瀯閫犲畠鐨勪笂涓绾у師鍨嬪璞★紝濡傛涓绾т竴绾х殑鍏崇郴閾撅紝灏辨瀯鎴愪簡鍘熷瀷閾俱傚師鍨嬮摼鐨勬渶椤剁灏辨槸Object.prototype 锛涘師鍨嬮摼鐨勫舰鎴愬氨鏄璞$殑灞炴у拰鏂规硶锛屾湁鍙兘鏄畾涔夊湪鑷韩鍐呯殑锛屼篃鏈夊彲鑳戒細瀹氫箟浠...
  • 鍘熷瀷瀵硅薄鍜屽璞″師鍨嬩互鍙鍘熷瀷閾
    绛旓細鈶犲彧瑕佹槸 瀵硅薄 灏 鏈塤_proto__ 鍘熷瀷锛屾寚鍚 鍘熷瀷瀵硅薄 鈶 瀹炰緥 鐨勫師鍨嬪璞¢噷闈㈢殑 __proto__ 鍘熷瀷鎸囧悜鐨勬槸 Object.prototype 鈶 Object.prototype 閲岄潰鐨 __proto__ 鍘熷瀷鎸囧悜鐨勬槸 null 鈶g敱__proto__鍘熷瀷杩炴帴鑰屾垚鐨'閾惧瓙'灏辨槸鍘熷瀷閾
  • 澶у巶甯歌闈㈣瘯:鍘熷瀷涓庡師鍨嬮摼
    绛旓細绛旀锛氬師鍥狅細1锛 ECMAScript瑙勫畾浜嗕袱涓壒娈婄殑鍐呯疆瀵硅薄锛 Object 鍜 Function 锛屼粬浠殑鐗规畩鎬у湪浜庯紝浠栦滑鏈韩鏄 鍑芥暟瀵硅薄 锛岃屼粬浠悓鏃朵篃鏄 鏋勯犲嚱鏁 銆 锛堝嚱鏁板璞″搴旂殑绫诲瀷鏄 Function 锛屾濡傛暟缁勫璞″搴旂殑绫诲瀷鏄 Array 锛涙甯哥殑鏋勯犲嚱鏁帮紝灏辨槸 new Fn() 銆 锛2锛 鍘熷瀷閾鏄璞$殑闆嗗悎锛屾瘡涓璞...
  • 濡備綍鍦ㄩ潰璇曚腑鍥炵瓟鈥滆璇翠粈涔堟槸鍘熷瀷鍜屽師鍨嬮摼鈥?
    绛旓細瀵逛簬鍑芥暟鑰岃█锛屽彧鏈夊嚱鏁版墠鏈 prototype 灞炴э紝Person.prototype 鏄竴涓璞★紝骞朵笖鏈変袱涓睘鎬э紝 涓涓槸 constructor 鎸囧悜鍏舵瀯閫犲嚱鏁 Person锛 涓涓槸 __proto__ 灞炴э細鏄竴涓璞★紝鎸囧悜涓婁竴灞傜殑鍘熷瀷銆鍘熷瀷閾鐨勫敖澶存槸Object.prototype銆傛墍鏈夊璞″潎浠嶰bject.prototype缁ф壙灞炴с侳unction.prototype鍜孎unction.__...
  • 鍘熷瀷璺熷師鍨嬮摼鍖哄埆鏄粈涔?鏈夊ぇ绁炲彲浠ヨВ閲婁竴涓嬪悧?璇蜂笉瑕佺櫨搴﹀鍒剁矘璐磋繃鏉...
    绛旓細鍩虹鐭ヨ瘑 鍦↗avaScript涓,涓鍏辨湁涓ょ绫诲瀷鐨勫,鍘熷鍊煎拰瀵硅薄鍊.姣忎釜瀵硅薄閮芥湁涓涓唴閮ㄥ睘鎬[prototype]],鎴戜滑閫氬父绉颁箣涓哄師鍨.鍘熷瀷鐨勫煎彲浠ユ槸涓涓璞,涔熷彲浠ユ槸null.濡傛灉瀹冪殑鍊兼槸涓涓璞,鍒欒繖涓璞′篃涓瀹氭湁鑷繁鐨勫師鍨.杩欐牱灏卞舰鎴愪簡涓鏉$嚎鎬х殑閾,鎴戜滑绉颁箣涓鍘熷瀷閾.璁块棶涓涓璞$殑鍘熷瀷鍙互浣跨敤ES5涓殑...
  • javascript鍘熷瀷,鍘熷瀷閾 鏈変粈涔堢壒鐐
    绛旓細javascript鍘熷瀷锛鍘熷瀷閾鐗圭偣锛氬師鍨嬮摼瀹炵幇浜嗙户鎵裤侸S涓瘡涓嚱鏁伴兘瀛樺湪鏈変竴涓師鍨嬪璞″睘鎬rototype銆傚苟涓旀墍鏈夊嚱鏁扮殑榛樿鍘熷瀷閮芥槸Object鐨勫疄渚嬨傛瘡涓户鎵跨埗鍑芥暟鐨勫瓙鍑芥暟鐨勫璞¢兘鍖呭惈涓涓唴閮ㄥ睘鎬roto銆傝灞炴у寘鍚竴涓寚閽堬紝鎸囧悜鐖跺嚱鏁扮殑prototype銆傝嫢鐖跺嚱鏁扮殑鍘熷瀷瀵硅薄鐨刜proto_灞炴т负鍐嶄笂涓灞傚嚱鏁般傚湪姝よ繃绋嬩腑灏...
  • JavaScript鍘熷瀷,鍘熷瀷閾 鏈変粈涔堢壒鐐
    绛旓細鎵鏈夌殑鏋勯犲嚱鏁扮殑prototype閮戒笉鑳戒负绌, 灏辨槸璇碨uperman.prototype = null 浼氳瑙i噴寮曟搸鏃犺; 鍙︿竴鏂归潰, Object鏋勯犲嚱鏁颁篃鏈塸rototype灞炴(璇ュ睘鎬ф槸鍙鐨, 鍙互涓哄師鍨嬪鍔犲睘鎬,浣嗕笉鑳借祴浜堜笉鍚岀殑瀵硅薄), 鏁呭洜姝ゅ彲浠ユ湁澶氬眰鐨鍘熷瀷閾, 浣嗗師鍨嬮摼鐨勬牴蹇呭畾浼氭槸Object.prototype . 杩欐剰鍛崇潃缁橭bject.prototype...
  • js涓粈涔堟槸鍘熷瀷瀵硅薄鍜屽師鍨嬮摼
    绛旓細姣忎釜 JavaScript 瀵硅薄鍐呴儴閮芥湁涓涓寚鍚戝叾瀹冨璞$殑鈥滄寚閽堚濇垨鑰 鈥滃紩鐢ㄢ滐紝 骞堕氳繃杩欑鏂瑰紡鍦ㄥ璞′箣闂村缓绔嬩簡涓绉嶈仈绯伙紝褰㈡垚浜嗕竴绉嶉摼寮忕粨鏋勶紝鎴戠殑鐞嗚В杩欏氨鏄墍璋撶殑鍘熷瀷閾銆俧unction F() {} // F 鏄竴涓嚱鏁帮紝鍑芥暟涔熸槸瀵硅薄锛岃屼笖姣忎釜鍑芥暟閮芥湁涓涓睘鎬у彨锛"prototype"var o = new F(); // F....
  • js toString璇﹁В
    绛旓細瑕佹兂寮勬噦tostring锛屾垜浠鍏堣鐞嗚В鍘熷瀷鍜屽師鍨嬮摼銆備笂鍥句负鍘熷瀷閾剧殑绀烘剰鍥俱倀oString()** 鏂规硶杩斿洖涓涓〃绀鸿瀵硅薄鐨勫瓧绗︿覆銆 姣忎釜瀵硅薄閮芥湁涓涓 toString() 鏂规硶锛屽綋璇ュ璞¤琛ㄧず涓轰竴涓枃鏈兼椂锛屾垨鑰呬竴涓璞′互棰勬湡鐨勫瓧绗︿覆鏂瑰紡寮曠敤鏃惰嚜鍔ㄨ皟鐢ㄣ傞粯璁ゆ儏鍐典笅锛 toString() 鏂规硶琚瘡涓 Object ...
  • 扩展阅读:原型链面试的时候怎么说 ... js原型和原型链的理解 ... 前端面试原型和原型链 ... 原型链图解 ... 原型对象原型链 ... 原型和原形链 ... 程兵警察原型真实案例 ... 原型原型链js通俗易懂 ... 原型原型链最简单的理解 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网