摘要:的面向對象主要包含了兩塊創(chuàng)建對象繼承。構造函數(shù)一般來說,我們可以這樣定義構造函數(shù)構造函數(shù)的函數(shù)名常大寫在這里,我們沒有顯示的創(chuàng)建對象,沒有語句,卻將屬性和方法賦值給了。
面向對象是軟件開發(fā)方法。面向對象的概念和應用已超越了程序設計和軟件開發(fā),擴展到如數(shù)據(jù)庫系統(tǒng)、交互式界面、應用結構、應用平臺、分布式系統(tǒng)、網(wǎng)絡管理結構、CAD技術、人工智能等領域。面向對象是一種對現(xiàn)實世界理解和抽象的方法,是計算機編程技術發(fā)展到一定階段后的產(chǎn)物。
JavaScript的面向對象主要包含了兩塊:1)創(chuàng)建對象 2)繼承。接下來,我們將走進JS對象的世界,將依次帶你深入了解函數(shù)、閉包、原型、原型鏈,并通過它們,最終實現(xiàn)創(chuàng)建對象和繼承。
如果現(xiàn)在有一個純牛奶,那么我們創(chuàng)建對象可以這樣操作:
var milk ={ name:"純牛奶", taste:"pure", price:4 }
那么如果現(xiàn)在有4種不同口味的牛奶呢?也創(chuàng)建四個不同的對象嗎?milk1、milk2、milk3、milk4?若有一萬種呢,是否也創(chuàng)建一萬個對象?
顯然,這是不合理的。這里,我們就要引入一個概念——工廠模式。
function createMilk(name,taste,price){ return { name:name, taste:taste, price:price } } var milk1 = createMilk("純牛奶","pure",4); var milk2 = createMilk("有機奶","organic",4); var milk3 = createMilk("低脂奶","low-fat",4);
在這里,我們實用一個函數(shù),傳入產(chǎn)品名、口味、價格3個參數(shù),返回一個對象。這樣,我們只要調(diào)用這個函數(shù),并傳入不同的參數(shù),即可構建不同的對象。這就是工廠模式。
工廠模式有優(yōu)點也有缺點:
1)優(yōu)點:簡單易懂、常見且實用。
2)缺點:對于如何證明我是一個牛奶這個問題上,則無法證明。//這句如若無法理解的話,可以暫時忽略,繼續(xù)往下看哦!
為了更好的講解構造函數(shù)、原型、原型鏈等,建議你復習一下函數(shù)的一些基礎知識,如果你已經(jīng)對函數(shù)有深入的了解,可以選擇跳過。戳這里:JS函數(shù)的一些基礎知識
構造函數(shù)還記得我們之前在講述工廠模式的缺點時,所說的那句“對于如何證明我是一個牛奶這個問題上,則無法證明。”嗎?接下來,就是見證奇跡的時刻!
var obj = new Object(); var add = new Function("a","b","return a+b"); console.log(obj instanceof Object);//true console.log(add instanceof Function);//true
Object和Function都是原生的構造函數(shù),在這里我們就可以使用instanceof來判斷是否為它的一個實例——即:證明了我就是一個牛奶哦!!
既然有原生的構造函數(shù),那么我們可以不可以也自己定義構造函數(shù)呢?答案是可以的。
一般來說,我們可以這樣定義構造函數(shù):
//構造函數(shù)的函數(shù)名常大寫 //在這里,我們沒有顯示的創(chuàng)建對象,沒有return語句,卻將屬性和方法賦值給了this。 function Milk(name,taste,price){ this.name = name; this.taste = taste; this.price = price; } //new操作符會默認的創(chuàng)建一個新對象,將function的this指向對象,然后將該對象賦值,對象就有了三個屬性。 var milk1 = new Milk("純牛奶","pure",4); console.log(milk1 instanceof Milk);//true
function Milk(name,taste,price){ this.name = name; this.taste = taste; this.price = price; this.say = function(){ console.log("Hello World"); }; } var milk1 = new Milk("純牛奶","pure",4); var milk2 = new Milk("純牛奶","pure",4);
假設我們創(chuàng)建了一個Milk的構造函數(shù),里面除了屬性還帶有一個say的方法,當我們new了兩個對象之后,兩個對象milk1和milk2是否都包含了功能相同的say方法呢?
這就是構造函數(shù)的不足之處:功能相同的函數(shù),重復聲明消耗空間!看來,我們的路還沒有走到終點。
原型是函數(shù)的一個屬性,是一個對象。如果函數(shù)作為構造函數(shù)使用,那么這個構造函數(shù)的所有實例,都共享這個原型對象。
「注」之前我們回憶函數(shù)時,回憶到,函數(shù)有三個常見屬性:name,length和prototype喔!如果遺忘,可以戳這里:JS函數(shù)的一些基礎知識!
1)constructor
原型的constructor是一個對象,我們可以這樣簡單的驗證一下:
Object.prototype.constructor === Object //true
2)讀寫
function Milk() {} Milk.prototype.name = "純牛奶"; Milk.prototype.taste = "pure"; Milk.prototype.price = 4; Milk.prototype.say = function(){ console.log("Hello World"); }; var milk1 = new Milk();
運行的結果如下:
通過這種方式,可以解決內(nèi)存問題。但也會因此而共享name,taste,price和say(),尤其是共享name,taste和price,會產(chǎn)生問題。
3)isPrototypeOf
我們可以通過isPrototypeOf來進行原型的判定,如下:
function Milk() {} Milk.prototype.name = "純牛奶"; Milk.prototype.taste = "pure"; Milk.prototype.price = 4; Milk.prototype.say = function(){ console.log("Hello World"); }; var milk1 = new Milk(); console.log(Milk.prototype.isPrototypeOf(milk1));//true
原型是函數(shù)的一個屬性,是一個對象。如果函數(shù)作為構造函數(shù)使用,那么這個構造函數(shù)的所有實例,都共享這個原型對象。
原型的不足,本質(zhì)上是共享的缺陷。我們可以看如下一段代碼:
var price = 10; var priceCopy = price; priceCopy = 20; console.log(price,priceCopy);//10,20
我們再看如下一段代碼:
var taste = ["pure","organic"]; var tasteCopy = taste; tasteCopy.push("low fat"); console.log(taste,tasteCopy);//["pure", "organic", "low fat"],["pure", "organic", "low fat"]
由此我們可見:
對于基本類型,price和priceCopy是在內(nèi)存中分別挖兩塊地方存儲,因此,priceCopy的值改變的時候,并不影響price的值;
而對于引用類型,name和nameCopy是調(diào)用同一個引用,引用同一個數(shù)據(jù),當我們在nameCopy添加一個名稱的時候,引用的數(shù)據(jù)就添加了一個值,name也就因此而受到了影響,這就是數(shù)據(jù)的污染。
共享會污染數(shù)據(jù)類型,因此原型創(chuàng)建對象也會污染數(shù)據(jù)類型。我們看下面一段代碼:
function Milk(){} Milk.prototype.taste = ["pure","organic"]; var m1 = new Milk(); var m2 = new Milk(); m2.taste.push("low fat"); console.log("m1",m1.taste);//["pure", "organic", "low fat"] console.log("m2",m2.taste);//["pure", "organic", "low fat"]
通過這段代碼,我們可以清楚的了解到原型創(chuàng)建對象主要的不足具體表現(xiàn)在:
原型創(chuàng)建對象會產(chǎn)生共享的問題
不能再額外傳遞參數(shù)進去。
構造函數(shù)結合原型構造函數(shù)有一定的優(yōu)缺點,原型也有一定的優(yōu)缺點,如果我們把兩者優(yōu)點結合,將會是一種不錯的創(chuàng)建對象的方式。我們看如下的代碼:
function Milk(name,taste,price){//構造函數(shù)獨享屬性 this.name = name; this.taste = taste; this.price = price; } Milk.prototype.say = function(){//原型共享方法 console.log(this.name); } var m1 = new Milk("純牛奶","pure","4"); m1.say();//純牛奶
在這段代碼中,我們使用構造函數(shù)來獨享屬性,以避免原型創(chuàng)建對象會產(chǎn)生的共享問題,當然,我們也使用原型共享方法,從而達到拒絕功能相同的函數(shù)導致的重復聲明消耗空間問題。
構造函數(shù)結合原型的一些細節(jié)問題在學習來構造函數(shù)結合原型創(chuàng)建對象的基礎之上,我們來關心一些細節(jié)性的問題,以便于我們深入了解構造函數(shù)結合原型。如,構造函數(shù)和原型上的屬性是否會覆蓋,優(yōu)先順序又是什么?再如,如何判斷屬性是在原型上還是在構造函數(shù)之上呢?
1)屬性的覆蓋
我們通過如下兩段代碼,總結關于構造函數(shù)結合原型的屬性覆蓋:
//1 function Milk(name,taste,price){//構造函數(shù)獨享屬性 this.name = name; this.taste = taste; this.price = price; } Milk.prototype.name = "牛奶"; Milk.prototype.say = function(){//原型共享方法 console.log(this.name); } var m1 = new Milk("純牛奶","pure","4"); console.log(m1.name);//純牛奶
//2 function Milk(name,taste,price){//構造函數(shù)獨享屬性 //this.name = name; this.taste = taste; this.price = price; } Milk.prototype.name = "牛奶"; Milk.prototype.say = function(){//原型共享方法 console.log(this.name); } var m1 = new Milk("純牛奶","pure","4"); console.log(m1.name);//牛奶
從兩端代碼中,我們對比得知,實例上的屬性會覆蓋原型上的屬性。即:會先在實例中查找,如沒有,則再在原型上查找。
2)屬性的判斷
(1)in操作符
我們可以通過如下三段代碼,總結關于in操作符的知識,即:只要對象里有值,即無論是在構造函數(shù)之上還是在原型之上均返回true,若都不在,則返回false。
//1 function Milk(name,taste,price){//構造函數(shù)獨享屬性 this.name = name; this.taste = taste; this.price = price; } Milk.prototype.say = function(){//原型共享方法 console.log(this.name); } var m1 = new Milk("純牛奶","pure","4"); console.log("name" in m1);//ture
//2 function Milk(name,taste,price){//構造函數(shù)獨享屬性 //this.name = name; this.taste = taste; this.price = price; } Milk.prototype.name = "牛奶"; Milk.prototype.say = function(){//原型共享方法 console.log(this.name); } var m1 = new Milk("純牛奶","pure","4"); console.log("name" in m1);//ture
//3 function Milk(name,taste,price){//構造函數(shù)獨享屬性 //this.name = name; this.taste = taste; this.price = price; } //Milk.prototype.name = "牛奶"; Milk.prototype.say = function(){//原型共享方法 console.log(this.name); } var m1 = new Milk("純牛奶","pure","4"); console.log("name" in m1);//false
(2)hasOwnProperty
我們可以通過如下兩段代碼,總結關于in操作符的知識,即:判斷是在實例上還是原型上,掛在實例上返回true,反之false。
//1 function Milk(name,taste,price){//構造函數(shù)獨享屬性 this.name = name; this.taste = taste; this.price = price; } //Milk.prototype.name = "牛奶"; Milk.prototype.say = function(){//原型共享方法 console.log(this.name); } var m1 = new Milk("純牛奶","pure","4"); console.log(m1.hasOwnProperty("name"));//true
//2 function Milk(name,taste,price){//構造函數(shù)獨享屬性 //this.name = name; this.taste = taste; this.price = price; } Milk.prototype.name = "牛奶"; Milk.prototype.say = function(){//原型共享方法 console.log(this.name); } var m1 = new Milk("純牛奶","pure","4"); console.log(m1.hasOwnProperty("name"));//false小結
在創(chuàng)建對象這個板塊中,我們從工廠模式開始講起,再到構造函數(shù),接著到原型,最后到比較完善的構造函數(shù)結合原型,在接下來的繼承板塊中,我們將講述原型鏈、繼承以及最佳方式的相關知識,好好復習!
繼承(更新中)當然,最最最最最后,如果您喜歡這片文章,可以瘋狂點贊或者收藏喔!!?
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93187.html
摘要:如果沒有學習過計算機科學的程序員,當我們在處理一些問題時,比較熟悉的數(shù)據(jù)結構就是數(shù)組,數(shù)組無疑是一個很好的選擇。 showImg(https://segmentfault.com/img/bVTSjt?w=400&h=300); 1、常見 CSS 布局方式詳見: 一些常見的 CSS 布局方式梳理,涉及 Flex 布局、Grid 布局、圣杯布局、雙飛翼布局等。http://cherryb...
摘要:如果沒有學習過計算機科學的程序員,當我們在處理一些問題時,比較熟悉的數(shù)據(jù)結構就是數(shù)組,數(shù)組無疑是一個很好的選擇。 showImg(https://segmentfault.com/img/bVTSjt?w=400&h=300); 1、常見 CSS 布局方式詳見: 一些常見的 CSS 布局方式梳理,涉及 Flex 布局、Grid 布局、圣杯布局、雙飛翼布局等。http://cherryb...
摘要:設計模式是以面向對象編程為基礎的,的面向對象編程和傳統(tǒng)的的面向對象編程有些差別,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設計模式必須要先搞懂面向對象編程,否則只會讓你自己更痛苦。 JavaScript 中的構造函數(shù) 學習總結。知識只有分享才有存在的意義。 是時候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...
摘要:在規(guī)范中,引入了的概念。使用中的聲明一個類,是非常簡單的事。中面向對象實例化的背后原理,實際上就是原型對象。與區(qū)別理解上述原理后,還需要注意與屬性的區(qū)別。實際上,在中,類繼承的本質(zhì)依舊是原型對象。 在 ES6 規(guī)范中,引入了 class 的概念。使得 JS 開發(fā)者終于告別了,直接使用原型對象模仿面向對象中的類和類繼承時代。 但是JS 中并沒有一個真正的 class 原始類型, clas...
閱讀 3152·2021-11-04 16:09
閱讀 3107·2021-09-23 11:49
閱讀 3603·2021-09-09 09:33
閱讀 3605·2021-08-18 10:22
閱讀 2041·2019-08-30 15:55
閱讀 3625·2019-08-30 15:53
閱讀 2653·2019-08-28 18:08
閱讀 888·2019-08-26 18:18