Javascript 对象一(对象详解)
JS創(chuàng)建對象的幾種方法
1. Object 構(gòu)造函數(shù) 創(chuàng)建
2. 對象字面量表示法 創(chuàng)建
3. 使用工廠模式創(chuàng)建對象
在 Car 函數(shù)中,返回的是一個對象。那么我們就無法判斷返回的對象究竟是一個什么樣的類型。于是就出現(xiàn)了第四種創(chuàng)建對象的模式
4. 使用構(gòu)造函數(shù)創(chuàng)建對象
構(gòu)造函數(shù)始終要應(yīng)該以一個大寫字母開頭,而非構(gòu)造函數(shù)則應(yīng)該以一個小寫字母開頭。
構(gòu)造函數(shù)與工程模式相比:
沒有顯示地創(chuàng)建對象
直接將屬性和方法賦給了this對象
沒有return語句
終于可以識別的對象的類型,可以使用instanceof操作符來進行自主檢測
構(gòu)造函數(shù)執(zhí)行流程:
構(gòu)造函數(shù)創(chuàng)建對象的缺點:
每個對象里面都有公用的函數(shù),就是每個方法都要在每個實例上重新創(chuàng)建一遍,如果方法的數(shù)量很多,就會占用很多不必要的內(nèi)存。
于是出現(xiàn)了第五種創(chuàng)建對象的方法
5. 原型創(chuàng)建對象模式
6. 組合使用構(gòu)造函數(shù)模式和原型模式
這種模式是ECMAScript中使用最廣泛,認可度最高的一種創(chuàng)建自定義類型的方法,可以說這是用來定義引用類型的一種默認模式
原型、原型鏈
原型prototype:在javascript中,每個函數(shù)都有一個特殊的屬性叫作原型(prototype)。注意函數(shù)對象才有prototype屬性。prototype屬性又指向了一個prototype對象
__proto__屬性:每個對象(除了null)都擁有這樣一個屬性,這個屬性是一個指針,它指向一個名叫做原型對象的內(nèi)存堆。而原型對象也是一個對象,因此又含有自己的[[prototype]]屬性,又指向下一個原型對象,終點指向我們的Object.prototype對象。
constructor 屬性:每個實例對象都從原型中繼承了一個constructor屬性,存在于每一個function的prototype屬性中,這個constructor保存了指向function的一個引用
在 constructor 屬性的末尾添加一對圓括號括號中包含所需的參數(shù))實例對象也可以百年城構(gòu)造器創(chuàng)建另一個對象實例
constructor屬性不影響任何javascript的內(nèi)部屬性。instanceof檢測對象的原型鏈,通常你是無法修改的。
constructor其實沒有什么用,只是javascript語言設(shè)計的歷史遺留物。
原型鏈:
1)原型鏈的最高指向: null
所有函數(shù)的默認原型都是Object的實例,因此默認原型都會包含一個內(nèi)部指針,指向Object.prototype。 Object的指針最后指向null
2)實例和原型的關(guān)系:
當(dāng)讀取實例的屬性時,如果找不到實例的屬性,就會查找與對象關(guān)聯(lián)的原型的屬性,如果還是查找不到,就查找原型的原型,一直到頂級為止。這樣就構(gòu)成了一個原型鏈
3) 原型的原型:
實例出來的var person = new Person()person通過__proto__指向構(gòu)造函數(shù)的原型Person.prototype,然后構(gòu)造函數(shù)的原型指向Object的原型,即是Person.prototype.__proto__指向Object.prototype。
實例講解:
function Person(name){this.name = name; } Person.prototype.sayName = function(){console.log(this.name); }var person = new Person("Lotus"); person.age = 23; person.sayName(); // Lotus <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>canvas</title><style>body{margin: 0;padding: 0;position: relative;}#myCanvas{position: absolute;left: 50%;top: 50%;background: #000;margin-left: -300px;margin-top: -150px;}</style> </head> <body><canvas id="myCanvas" width="600" height="300" style="border: 1px solid #000;"></canvas><script type="text/javascript">window.onload = function(){var c = document.getElementById('myCanvas');var grd = ""; // 漸變的顏色// 上下文var context = c.getContext("2d");if(context){// x,y,r 坐標(biāo)和半徑function Star(x,y,r){this.x = x;this.y = y;this.r = r;this.init(this.x,this.y,this.r);}// 繪制星星Star.prototype.init = function(x,y,r){context.beginPath();// 漸變顏色grd = context.createRadialGradient(x,y,r-2,x,y,r+2)grd.addColorStop(0, 'white');grd.addColorStop(1, 'yellow');context.fillStyle=grd;// 畫圓context.arc(x,y,r,0,2*Math.PI);// 填充顏色context.fill();context.closePath();}// 創(chuàng)建星星for(var i = 0; i < 200; i++){var x = Math.floor(Math.random()*600);var y = Math.floor(Math.random()*300);var r = Math.floor(Math.random()*3)+2;new Star(x,y,r)}}else{var div = document.createElement("div");div.innerHTML = "您的瀏覽器不支持canvas,請升級瀏覽器!";document.getElementsByTagName("body")[0].appendChild(div);}}</script> </body> </html>繼承
- 構(gòu)造函數(shù)、原型和實例之間的關(guān)系:
每個構(gòu)造函數(shù)都有一個原型對象,原型對象都包含一個指向構(gòu)造函數(shù)的指針,而實例都包含一個原型對象的指針。 - 繼承的本質(zhì):即重寫原型對象,代之以一個新類型的實例。
1、原型鏈繼承
function SuperType() {this.property = true; }SuperType.prototype.getSuperValue = function() {return this.property; }function SubType() {this.subproperty = false; }// 這里是關(guān)鍵,創(chuàng)建SuperType的實例,并將該實例賦值給SubType.prototype SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function() {return this.subproperty; }var instance = new SubType(); console.log(instance.getSuperValue()); // true
存在的缺點:多個實例對引用類型的操作會被篡改。
2、借用構(gòu)造函數(shù)繼承
使用父類的構(gòu)造函數(shù)來增強子類實例,等同于復(fù)制父類的實例給子類(不使用原型)
缺點:
只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法
無法實現(xiàn)復(fù)用,每個子類都有父類實例函數(shù)的副本,影響性能
3、組合繼承
用原型鏈實現(xiàn)對原型屬性和方法的繼承,用借用構(gòu)造函數(shù)技術(shù)來實現(xiàn)實例屬性的繼承。
缺點:
第一次調(diào)用SuperType():給SubType.prototype寫入兩個屬性name,color。
第二次調(diào)用SuperType():給instance1寫入兩個屬性name,color。
缺點就是在使用子類創(chuàng)建實例對象時,其原型中會存在兩份相同的屬性/方法。
4、原型式繼承
利用一個空對象作為中介,將某個對象直接賦值給空對象構(gòu)造函數(shù)的原型。
缺點:
原型鏈繼承多個實例的引用類型屬性指向相同,存在篡改的可能。
無法傳遞參數(shù)
ES5中存在Object.create()的方法,能夠代替上面的object方法
5、寄生式繼承
在原型式繼承的基礎(chǔ)上,增強對象,返回構(gòu)造函數(shù)
缺點:跟4原型式繼承一樣
6、寄生組合式繼承
結(jié)合借用構(gòu)造函數(shù)傳遞參數(shù)和寄生模式實現(xiàn)繼承
7、混入方式繼承多個對象
8、ES6類繼承extends
extends關(guān)鍵字主要用于類聲明或者類表達式中,以創(chuàng)建一個類,該類是另一個類的子類。其中constructor表示構(gòu)造函數(shù),一個類中只能有一個構(gòu)造函數(shù),有多個會報出SyntaxError錯誤,如果沒有顯式指定構(gòu)造方法,則會添加默認的 constructor方法,使用例子如下。
extends繼承的核心代碼如下,其實現(xiàn)和上述的寄生組合式繼承方式一樣
function _inherits(subType, superType) {// 創(chuàng)建對象,創(chuàng)建父類原型的一個副本// 增強對象,彌補因重寫原型而失去的默認的constructor 屬性// 指定對象,將新創(chuàng)建的對象賦值給子類的原型subType.prototype = Object.create(superType && superType.prototype, {constructor: {value: subType,enumerable: false,writable: true,configurable: true}});if (superType) {Object.setPrototypeOf ? Object.setPrototypeOf(subType, superType) : subType.__proto__ = superType;} }查看原文:
https://juejin.im/post/5b150fcf518825139b18de11#heading-0
https://juejin.im/post/5acf22aef265da238c3b0f78#heading-3
https://juejin.im/post/5bcb2e295188255c55472db0
總結(jié)
以上是生活随笔為你收集整理的Javascript 对象一(对象详解)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: unity3d大型互动照片墙
- 下一篇: 【树莓派学习笔记】三、点亮一个LED灯(