摘要:而和的存在就是為了建立這種子類與父類間的聯(lián)系。創(chuàng)建一個(gè)基本對(duì)象建立新對(duì)象與原型我把它理解為類之間的連接執(zhí)行構(gòu)造函數(shù)小結(jié)可以理解為類,也就是存儲(chǔ)一類事物的基本信息。原型原型鏈和繼承之間的關(guān)系。
原型 原型的背景
首先,你應(yīng)該知道javascript是一門面向?qū)ο笳Z言。
是對(duì)象,就具有繼承性。
繼承性,就是子類自動(dòng)共享父類的數(shù)據(jù)結(jié)構(gòu)和方法機(jī)制。
而prototype 和 __proto__ 的存在就是為了建立這種子類與父類間的聯(lián)系。
我們將prototype稱作原型,將通過__proto__來建立起來的對(duì)象與對(duì)象的關(guān)系稱作原型鏈。
下面,通過創(chuàng)建一個(gè)簡(jiǎn)單對(duì)象,來探索原型和原型鏈到底是什么。
原型與原型鏈首先,創(chuàng)建一個(gè)最簡(jiǎn)單的對(duì)象
function Foo(){} var o = new Foo();
ps:這是剛從java轉(zhuǎn)入JavaScript時(shí),最令我費(fèi)解的一段代碼,憑什么一個(gè)function就可以用來創(chuàng)建一個(gè)對(duì)象。下面就是new 關(guān)鍵字的分解動(dòng)作。。。這個(gè)關(guān)鍵字究竟做了什么,能創(chuàng)建一個(gè)對(duì)象。。
這個(gè)創(chuàng)建的過程,可以分解成下面代碼
function Foo(){} // 創(chuàng)建一個(gè)基本對(duì)象 var o = new Object(); // 創(chuàng)建對(duì)象和父類原型之間的鏈接 o.__proto__ = Foo.prototype; // 執(zhí)行構(gòu)造函數(shù) Foo.call(o);
為了更好的理解這段代碼,我們先理解這幾個(gè)概念
構(gòu)造函數(shù)就是對(duì)象創(chuàng)建時(shí),自動(dòng)調(diào)用的方法
prototype,長(zhǎng)這樣
{ constructor: f foo() __proto__: Object }
它是一個(gè)對(duì)象,存儲(chǔ)著一類事物的基本信息,所以可以將它稱作類。
__proto__,這個(gè)屬性用來建立對(duì)象和類之間的關(guān)系。
有了這些概念,我們來分析創(chuàng)建對(duì)象的過程中,究竟做了些什么.
創(chuàng)建一個(gè)對(duì)象,會(huì)做如下三件事。
創(chuàng)建一個(gè)基本對(duì)象 new Object()
建立新對(duì)象與原型(我把它理解為類)之間的連接
執(zhí)行構(gòu)造函數(shù)
小結(jié):prototype可以理解為類,也就是存儲(chǔ)一類事物的基本信息。__proto__可以理解為一條線索,用來建立原型(類)和對(duì)象之間的關(guān)系。
原型、原型鏈和繼承之間的關(guān)系。繼承,需要滿足如下三個(gè)要求。
子類繼承父類的成員變量
子類繼承父類的方法
子類繼承父類的構(gòu)造器,如果父類的構(gòu)造函數(shù)帶有參數(shù),那么子類中應(yīng)該顯示調(diào)用
我們?cè)撊绾螌?shí)現(xiàn)繼承呢?
// 創(chuàng)建一個(gè)構(gòu)造函數(shù),我認(rèn)為 a.prototype就是父類對(duì)象。 function a(x,y) { a.prototype.x = x; a.prototype.y = y } // 為父類對(duì)象添加一個(gè)method a.prototype.console = function() { console.log(this.x); console.log(this.y); } //創(chuàng)建子類構(gòu)造函數(shù) function b(x,y) { // 子類顯示的調(diào)用父類構(gòu)造方法 a.call(this,x,y); } // 子類繼承父類的成員變量以及父類的方法 b.prototype = Object.create(a.prototype); = b.prototype.constructor = b; // 創(chuàng)建對(duì)象 var c = new b(1,2);
// 這里Object.create 是用來創(chuàng)建一個(gè)新的prototype,用來記錄新類的信息,并與父類建立聯(lián)系 Object.create = function() { //創(chuàng)建一個(gè)基本對(duì)象 var temp = new Object(); //與父類的的原型建立聯(lián)系 temp.__proto__ = proto; //返回新類的原型 return temp; }
小結(jié):繼承關(guān)系的實(shí)現(xiàn),做了如下兩件事情
子類顯示的調(diào)用父類的構(gòu)造函數(shù)
子類通過原型來與父類建立聯(lián)系,從而能讓子類擁有父類的成員變量和方法。
原型就是類,原型鏈就是來建立子類和父類之間的聯(lián)系。
原型鏈的實(shí)際表現(xiàn)先創(chuàng)建一個(gè)類
function people() {} // 為父類對(duì)象添加一個(gè)method people.prototype.run = function() { console.log("I am running"); }
通過類來創(chuàng)建一個(gè)對(duì)象
var p = new people(); p.run(); // i am running
這里p對(duì)象長(zhǎng)這樣
{ __proto__: Object }
很顯然,這個(gè)對(duì)象之中并沒有run方法。
但是它卻能調(diào)用run,因?yàn)樗鼤?huì)通過__proto__(原型鏈)來尋找類中的方法。
經(jīng)常有人這么問proto 和prototype有什么區(qū)別?我想看到這里,你應(yīng)該很明白了。
prototype 一個(gè)存儲(chǔ)類信息的對(duì)象,只存在function中.(下圖中綠塊)
proto 單純是對(duì)象用來指向上級(jí)的一鏈接。(看下圖黃線)
那么又有人會(huì)問function中__proto__又是什么關(guān)系呢?
function 本身是對(duì)象,所以當(dāng)然也有自己原型。function繼承于Function.(看下圖藍(lán)線)。
下面介紹一下原型繼承和類繼承的關(guān)系。
原型繼承和類繼An example that shows the difference between creating a JavaScript class and subclass in ES5 and ES6.
ES5
"use strict"; /** * Shape class. * * @constructor * @param {String} id - The id. * @param {Number} x - The x coordinate. * @param {Number} y - The y coordinate. */ function Shape(id, x, y) { this.id = id; this.setLocation(x, y); } /** * Set shape location. * * @param {Number} - The x coordinate. * @param {Number} - The y coordinate. */ Shape.prototype.setLocation = function(x, y) { this.x = x; this.y = y; }; /** * Get shape location. * * @return {Object} */ Shape.prototype.getLocation = function() { return { x: this.x, y: this.y }; }; /** * Get shape description. * * @return {String} */ Shape.prototype.toString = function() { return "Shape("" + this.id + "")"; }; /** * Circle class. * * @constructor * @param {String} id - The id. * @param {Number} x - The x coordinate. * @param {Number} y - The y coordinate. * @param {Number} radius - The radius. */ function Circle(id, x, y, radius) { Shape.call(this, id, x, y); this.radius = radius; } Circle.prototype = Object.create(Shape.prototype); Circle.prototype.constructor = Circle; /** * Get circle description. * * @return {String} */ Circle.prototype.toString = function() { return "Circle > " + Shape.prototype.toString.call(this); }; // test the classes var myCircle = new Circle("mycircleid", 100, 200, 50); // create new instance console.log(myCircle.toString()); // Circle > Shape("mycircleid") console.log(myCircle.getLocation()); // { x: 100, y: 200 }
ES6
"use strict"; /** * Shape class. * * @constructor * @param {String} id - The id. * @param {Number} x - The x coordinate. * @param {Number} y - The y coordinate. */ class Shape(id, x, y) { constructor(id, x, y) { // constructor syntactic sugar this.id = id; this.setLocation(x, y); } /** * Set shape location. * * @param {Number} - The x coordinate. * @param {Number} - The y coordinate. */ setLocation(x, y) { // prototype function this.x = x; this.y = y; } /** * Get shape location. * * @return {Object} */ getLocation() { return { x: this.x, y: this.y }; } /** * Get shape description. * * @return {String} */ toString() { return `Shape("${this.id}")`; } } /** * Circle class. * * @constructor * @param {String} id - The id. * @param {Number} x - The x coordinate. * @param {Number} y - The y coordinate. * @param {Number} radius - The radius. */ function Circle extends Shape { constructor(id, x, y, radius) { super(id, x, y); // call Shape"s constructor via super this.radius = radius; } /** * Get circle description. * * @return {String} */ toString() { // override Shape"s toString return `Circle > ${super.toString()}`; // call `super` instead of `this` to access parent } } // test the classes var myCircle = new Circle("mycircleid", 100, 200, 50); // create new instance console.log(myCircle.toString()); // Circle > Shape("mycircleid") console.log(myCircle.getLocation()); // { x: 100, y: 200 }
這段代碼,自己體會(huì)。。。。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/89510.html
摘要:要搞清這三種關(guān)系指向之間的關(guān)系拗口,其實(shí)也就是要搞懂,構(gòu)造函數(shù)由構(gòu)造函數(shù)操作創(chuàng)造出的實(shí)例對(duì)象和構(gòu)造函數(shù)的原型對(duì)象之間的關(guān)系。 寫在前面 這篇博客來源于,有天mentor突然傳給我了這張祖?zhèn)鞯膱D片,并且發(fā)誓一定要給我講清楚,然鵝在他的一番激情講解之后,他自己也被繞懵了...于是后來我決定整理一下似乎還有點(diǎn)清晰的思路,記錄一下我對(duì)這張圖的理解。作為一個(gè)小白,對(duì)于js中這些比較復(fù)雜的概念的理...
摘要:繼承可以使得子類具有父類別的各種屬性和方法。繼承是類與類之間的關(guān)系。繼承的實(shí)質(zhì)就是兩次的原型搜索,像是實(shí)例屬性而不是繼承,才是繼承。更多用法見繼承。 前言 面試中最常會(huì)問到的問題:什么是繼承?如何分別用 ES5 和 ES6 實(shí)現(xiàn)?想要學(xué)習(xí)繼承,必須先學(xué)好原型與原型鏈,如果此部分還不清楚,請(qǐng)先學(xué)習(xí)此部分再來閱讀本文,可參考我的文章JS之原型與原型鏈或?yàn)g覽其他相關(guān)的學(xué)習(xí)網(wǎng)站。 定義 繼承...
之前也有和大家講過有關(guān)JS的對(duì)象創(chuàng)建和對(duì)象繼承,本篇文章主要為大家做個(gè)匯總和梳理。 JS中其實(shí)就是原型鏈繼承和構(gòu)造函數(shù)繼承的毛病,還有就是工廠、構(gòu)造、原型設(shè)計(jì)模式與JS繼承。 JS高級(jí)程序設(shè)計(jì)4:class繼承的重點(diǎn),不只是簡(jiǎn)簡(jiǎn)單單的語法而已。 對(duì)象創(chuàng)建 不難發(fā)現(xiàn),每一篇都離不開工廠、構(gòu)造、原型這3種設(shè)計(jì)模式中的至少其一! 那JS為什么非要用到這種3種設(shè)計(jì)模式了呢?? 我們先從對(duì)...
摘要:上一篇你不知道的筆記寫在前面這是年第一篇博客,回顧去年年初列的學(xué)習(xí)清單,發(fā)現(xiàn)僅有部分完成了。當(dāng)然,這并不影響年是向上的一年在新的城市穩(wěn)定連續(xù)堅(jiān)持健身三個(gè)月早睡早起游戲時(shí)間大大縮減,學(xué)會(huì)生活。 上一篇:《你不知道的javascript》筆記_this 寫在前面 這是2019年第一篇博客,回顧去年年初列的學(xué)習(xí)清單,發(fā)現(xiàn)僅有部分完成了。當(dāng)然,這并不影響2018年是向上的一年:在新的城市穩(wěn)定、...
摘要:請(qǐng)看對(duì)應(yīng)版本干了什么可知,相當(dāng)于以前在構(gòu)造函數(shù)里的行為。這種寫法會(huì)與上文中寫法有何區(qū)別我們?cè)诃h(huán)境下運(yùn)行一下,看看這兩種構(gòu)造函數(shù)的有何區(qū)別打印結(jié)果打印結(jié)果結(jié)合上文中關(guān)于原型的論述,仔細(xì)品味這兩者的差別,最好手動(dòng)嘗試一下。 ES6 class 在ES6版本之前,JavaScript語言并沒有傳統(tǒng)面向?qū)ο笳Z言的class寫法,ES6發(fā)布之后,Babel迅速跟進(jìn),廣大開發(fā)者也很快喜歡上ES6帶...
閱讀 1170·2021-11-15 18:14
閱讀 3640·2021-11-15 11:37
閱讀 762·2021-09-24 09:47
閱讀 2447·2021-09-04 16:48
閱讀 2187·2019-08-30 15:53
閱讀 2388·2019-08-30 15:53
閱讀 397·2019-08-30 11:20
閱讀 1241·2019-08-29 16:08