您好,登錄后才能下訂單哦!
這篇文章主要介紹“JavaScript原型對象怎么用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“JavaScript原型對象怎么用”文章能幫助大家解決問題。
你理解的類?類的特性有哪些?(封裝,繼承,多態)
類實際是一個“特殊的函數”,就像你能夠定義的函數表達式和函數聲明一樣,類語法也由兩個組成部分:類聲明和類表達式。類的主體都是在嚴格模式下執行的。
類的類體是由一對花括號{}中的部分,這是定義類成員的位置。【成員主要是方法或者構造函數】
類的所有方法都等價于是定義在類的prototype屬性上。在類的實列上調用方法,等同于在調用原型上的方法。
class A(){ constructor(){} a(){} b(){} } //等價于 A.prototype={constructor(){},a(){},b(){}}
組成:
構造函數:
constructor方法是一個特殊的方法,這種方法用于創建和初始化一個由class創建的對象。一個類只能有一個構造函數,如果多個會報錯,如果沒有會默認添加一個空的constructor。其中constructor默認返回實列對象【即this】。一個構造函數可以使用super關鍵字來調用一個父類的構造函數。
屬性
原型方法:該方法不需要加上function關鍵字,直接把函數的定義放進去就可以了。方法和方法之間不能用逗號分隔,會報錯。
靜態方法:使用static定義靜態方法,調用靜態方法,不能類的實列去調用,只能使用類去調用。
取值函數getter和存值函數setter:在類中使用get和set關鍵字,對某個屬性設置存值和取值函數,攔截該屬性的存取行為。
類語法:
類聲明:使用class關鍵字
class Rectangle{ constructor(height,width){ this.height=height; this.width=width; } }
注意:函數聲明和類聲明的區別:類聲明不會提升,函數聲明會提升。
類表達式:類表達式可以是被命名的或匿名的。賦予一個命名類表達式的名稱是類的主體的本地名稱。
let Rectangle=class{//匿名類 constructor(height,width){ this.height=height; this.width=width; } } let Rectangle= class Rectangle{//命名類 constructor(height,width){ this.height=height; this.width=width; } }
使用extends創建子類:
extends關鍵字在類聲明或類表達式中用于創建一個類作為另一個類的子類。
使用super調用超類:
super關鍵字用于調用對象的父對象上的函數
類的特性:
- 封裝:主要是通過函數,私有屬性和方法的設置主要是通過塊級作用域實現
- 多態:可以通過函數調用,因為參數是可以多變的
- 繼承:主要通過原型鏈
當我們在new一個普通函數時候,發生了什么?
以構造器的 prototype 屬性(注意與私有字段 [[prototype]] 的區分)為原型,創建新對象;
將this 和調用參數傳給構造器,執行;
如果構造器返回的是對象,則返回,否則返回第一步創建的對象。
new 這樣的行為,試圖讓函數對象的語法跟類變得相似,但是,它客觀上提供了兩種方式,一是在構造器中添加屬性,二是在構造器的 prototype 屬性上添加屬性。
new后面的函數名一定要大寫嗎?
不是,主要是為了便于區分類。一般約束為大寫
如何理解ProtoType?查找一個對象的某個屬性的過程?
prototype:
每個函數都有一個特殊的屬性叫做原型對象【prototype】
js是基于原型的語言,每個對象都擁有一個原型對象,對象以其原型為模板、從原型繼承方法和屬性。這些屬性和方法時定義在對象的構造函數之上的prototype屬性上,而非對象的實例本身。
原型對象可以再擁有原型對象,并從中繼承方法和屬性,一層一層,層層向上直到一個對象的原型對象為 null,這種就是原型鏈。
創建對象實例時,對象的實例和它的構造器之間建立一個鏈接【__proto__屬性,是從構造函數的prototype屬性派生的。也就是__proto__與構造函數的prototype是指向同個對象】Object.getPrototypeof(new Foobar())和Foobar.prototype是相等的。
Object.create()。是從指定的原型對象,創建一個新對象。var newObj=Object.create(obj)。則newObj的__proto__=obj
每個實列對象都從原型中繼承了一個constructor屬性。該屬性指向了構造此實例的構造函數。
一般都是構造器中定義屬性,在prototype定義方法。
一般由構造函數實列化出一個新對象,新對象的原型對象是一個constructor和一個Object的原型對象組成。而函數構造函數的原型對象是也是由另外一個constructor和一個Function的原型對象組成。
var F=function(){}; Object.prototype.a=function(){}; Function.prototype.b=function(){}; var f=new F(); //上面的結果是,f能取到a,不能取到b. 詳解: 1.f.__proto__===F.prototype 2.F.prototype.__proto__===Object.prototype(所以f可以訪問a) 3.f.constructor===F 4.F.__proto__===Function.prototype(所以f.constructor.b可以訪問)
查找屬性的過程:
1.先查找自己身屬性是否由包含該屬性。
2.如果沒有,才會沿著原型鏈,層層向上搜索,直到找到名字的屬性
3.如果找到最后原型鏈的末尾,即最后的原型為null,那就是沒有找到該屬性。就會返回undefined
不同方法創建對象和原型鏈
1.使用語法結構創建對象
var o = {a: 1}; // o 這個對象繼承了 Object.prototype 上面的所有屬性 // o 自身沒有名為 hasOwnProperty 的屬性 // hasOwnProperty 是 Object.prototype 的屬性 // 因此 o 繼承了 Object.prototype 的 hasOwnProperty // Object.prototype 的原型為 null // 原型鏈如下: // o ---> Object.prototype ---> null var a = ["yo", "whadup", "?"]; // 數組都繼承于 Array.prototype // (Array.prototype 中包含 indexOf, forEach 等方法) // 原型鏈如下: // a ---> Array.prototype ---> Object.prototype ---> null function f(){ return 2; } // 函數都繼承于 Function.prototype // (Function.prototype 中包含 call, bind等方法) // 原型鏈如下: // f ---> Function.prototype ---> Object.prototype ---> null
2.使用構造函數創建對象
function A() { this.a = 1; this.b = 2; } A.prototype = { write: function(){ console.log(this.a); } }; var a = new A(); // a 是生成的對象,他的自身屬性有 'a' 和 'b'。
3.使用Object.create()創建對象(ES5)
var a = {a: 1}; // a ---> Object.prototype ---> null var b = Object.create(a); // b ---> a ---> Object.prototype ---> null console.log(b.a); // 1 (繼承而來) var c = Object.create(b); // c ---> b ---> a ---> Object.prototype ---> null var d = Object.create(null); // d ---> null console.log(d.hasOwnProperty); // undefined, 因為d沒有繼承Object.prototype 使用
4.使用class創建對象(ES6)
class A { constructor(a, b) { this.a = a; this.b = b; } } class B extends A { constructor(a,b,c) { super(a, b); this.c=c; } get ab() { return this.a + this.b; } set d(d) { this.a = d; this.b = d; this.c = d; } } var a= new A('a','b');//a的原型對象是 A.prototype var b = new B('a','b','c');// //b的原型對象是 B.prototype
當一個對象設置屬性時都發生了什么?
如果對象包含普通數據訪問屬性,直接賦值只會修改屬性值
var a={b=1}//因為b是a的普通屬性,數據類型為Number
a.b="a"; //直接更改b的類型為String,且賦值為'a'.
如果對象找不到該屬性,且原型鏈也找不到,就直接默認添加一個屬性到該對象上。
var a={}//b不是a的普通屬性,且原型鏈上也沒有
a.b="a"; //直接在a上添加b的類型,為String,且賦值為'a'.
如果屬性b,存在于原型鏈上
//在原型鏈上層存在名為b的普通數據訪問屬性并且沒有標記為只讀(writable:false),那就會直接在a中添加一個名為b的新屬性,且值為'a'。而原型鏈上的b就會被屏蔽掉:
function A(){}; A.prototype.b=1; var a=new A(); a.b='a';
//在原型鏈上層存在b,但是他被標記為只讀,那么無法修改已有屬性,或者在a中創建屏蔽屬性。如果運行在嚴格模式下,代碼會拋出一個錯誤,否則,這條賦值語句會被忽略,總之,不會發生屏蔽。
function A(){ }; A.prototype.b=1 Object.defineProperty(A.prototype,'b',{ configurable:true, writable:false }) var a=new A(); a.b='a';//結果a.b還是1
關于“JavaScript原型對象怎么用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。