前端面向?qū)ο缶幊讨瓻S5語法ES6語法詳解
一.面向?qū)ο缶幊?/h2>
1.概念
- 通過對于具有相同屬性和函數(shù)方法的一類事物的描述,實現(xiàn)代碼功能
- 對于具有相同屬性和函數(shù)方法的抽象類實現(xiàn)代碼功能
2.理解
定義一個對象
利用對象的屬性存儲的數(shù)據(jù)
將程序執(zhí)行需要的數(shù)據(jù)都以屬性的形式,存儲在對象中
利用函數(shù)方法存儲程序代碼
將執(zhí)行程序需要的代碼
以函數(shù)方法的形式存儲
調(diào)用執(zhí)行函數(shù)方法時
使用的數(shù)據(jù)是對象屬性中存儲的數(shù)據(jù)
二.語法形式
工廠模式
function 函數(shù)(形參,形參...){ const obj= {}; //創(chuàng)建一個空對象 obj.屬性 = 屬性; obj.屬性 = 屬性; ... 設(shè)定對象的屬性和屬性值 obj.函數(shù)方法 = function(){} obj.函數(shù)方法 = function(){} ... 設(shè)定對象的函數(shù)方法 return obj; 返回值是這個創(chuàng)建的對象 } /* 工廠模式 是 創(chuàng)建 屬性和函數(shù)方法相同 屬性值不同的 對象 創(chuàng)建的對象 都 相同的屬性 不同的屬性值 還有 完全相同的函數(shù)方法 每一個對象都存儲了完全相同的函數(shù)方法 造成有 冗余的代碼程序 */
ES5語法
function 構(gòu)造函數(shù)(形參,形參...){ //在構(gòu)造函數(shù)中通過this指向設(shè)定操作對象的屬性 this.屬性 = 形參; this.屬性 = 形參; } //在構(gòu)造函數(shù)外在構(gòu)造函數(shù)的prototype中定義函數(shù) 構(gòu)造函數(shù).prototype.函數(shù)方法 = function(){} 構(gòu)造函數(shù).prototype.函數(shù)方法 = function(){} //通過new關(guān)鍵詞 調(diào)用構(gòu)造函數(shù)創(chuàng)建實例化對象
ES6語法
使用class關(guān)鍵詞定義構(gòu)造函數(shù) class 構(gòu)造函數(shù){ //在構(gòu)造函數(shù)中定義對象的屬性屬性值 constructor(形參,形參...){ this.屬性 = 形參; this.屬性 = 形參; } //在構(gòu)造函數(shù)外定義函數(shù)方法 js程序自動定義在prototype 中 函數(shù)方法(){} 函數(shù)方法(){} } const 實例化對象 = new 構(gòu)造函數(shù)(實參,實參...); 通過new關(guān)鍵詞調(diào)用構(gòu)造函數(shù)創(chuàng)建實例化對象
三.批量生產(chǎn)對象
字面量方式
const obj = {} obj.a = 1 obj.b = 2 console.log(obj) const obj1 = {} obj1.a = 1 obj1.b = 2 console.log(obj1) //不能批量生產(chǎn)
內(nèi)置構(gòu)造函數(shù)
const obj = new Object() obj.a = 1 obj.b = 2 console.log(obj) const obj1 = new Object() obj1.a = 1 obj1.b = 2 console.log(obj1) //不能批量生產(chǎn)
工廠函數(shù)
function createObj (name, age) { // 1. 手動創(chuàng)建一個對象 const obj = {} // 2. 手動向?qū)ο髢?nèi)部添加屬性 obj.name = name obj.age = age // 3. 手動返回一個對象 return obj } //這個方法能夠創(chuàng)建對象, 并且批量生產(chǎn)也可以
自定義構(gòu)造函數(shù)
function createObj () { // 1. 自動創(chuàng)建出來一個對象 // 2. 手動向?qū)ο筇砑訉傩? // 3. 自動返回一個對象 } const o1 = new createObj() // 這種調(diào)用方式, 才是 構(gòu)造函數(shù) const o2 = createObj() // 這就是一個普通函數(shù)的調(diào)用 console.log(o1) console.log(o2) /* 自定義構(gòu)造函數(shù), 本質(zhì)是就是一個函數(shù) 當(dāng)他和 new 關(guān)鍵字連用的時候, 就叫做構(gòu)造函數(shù) 自動創(chuàng)建一個對象 手動向創(chuàng)建的對象添加屬性 自動返回一個對象 */
四.自定義構(gòu)造函數(shù)的書寫
1. 一定是和new關(guān)鍵字連用
如果沒有和new連用,那么它就是一個普通函數(shù)
2.當(dāng)一個函數(shù)和new關(guān)鍵連用的時候,這個函數(shù)就被稱為自定義構(gòu)造函數(shù),這個函數(shù)內(nèi)容this指向,指向返回出來的對象
3.構(gòu)造函數(shù)不能使用給箭頭函數(shù)
因為箭頭函數(shù)內(nèi)部沒有this
4.構(gòu)造函數(shù)內(nèi)部不需要return
- return了基本數(shù)據(jù)類型,寫了和沒寫一樣
- return 了引用數(shù)據(jù)類型,寫了構(gòu)造函數(shù)就沒用了
5.書寫構(gòu)造函數(shù)時,首字母建議大寫
目的: 僅僅是為了和普通函數(shù)區(qū)分
6.我們構(gòu)造函數(shù)通過new關(guān)鍵字創(chuàng)建出來的對象,叫做實例化對象,本質(zhì)上還是一個對象,只不過名字上叫做實例化對象(實例對象)
我們把構(gòu)造函數(shù)通過new關(guān)鍵字創(chuàng)建對象的過程叫實例化
和普通函數(shù)一樣, 只不過 調(diào)用的時候要和 new 連用 不然就是一個普通函數(shù)調(diào)用
1.不寫new的時候就是普通函數(shù)調(diào)用,沒有創(chuàng)造對象的能力
function Person () {} var o1 = new Person() // 一個對象 var o2 = Person() // 什么也得不到, 就是一個普通函數(shù)的調(diào)用
2.首字母不大些, 只要和 new 連用, 就有創(chuàng)造對象的能力
function person () {} var o1 = new person() // 一個對象
3.當(dāng)調(diào)用的時候, 如果不需要傳遞參數(shù)可以不寫 ()
, 但是建議寫上
function person () {} var o1 = new person // 一個對象
5.構(gòu)造函數(shù)內(nèi)部的 this, 由于和 new 連用的關(guān)系, 是指向當(dāng)前實例對象的
function Person () { console.log(this) } var o1 = new Person() // this ---> o1 var o2 = new Person() // this ---> o2
五.使用構(gòu)造函數(shù)創(chuàng)建一個對象
function Person() { this.name = 'Jack' this.age = 18 } var o1 = new Person() var o2 = new Person()
function Person() { this.name = 'Jack' this.age = 18 this.sayHi = function () { console.log('hello word') } } var o1 = new Person() var o2 = new Person()
// 有缺點 function Person() { this.name = 'Jack' this.age = 18 this.sayHi = function () { console.log('hello word') } } /** * 第一次 new 的時候, Person 這個函數(shù)要執(zhí)行一遍 * 執(zhí)行一邊就會創(chuàng)造一個新的函數(shù), 并且把函數(shù)地址賦值給 this.sayHi */ var o1 = new Person() /** * 第二次 new 的時候, Person 這個函數(shù)要執(zhí)行一遍 * 執(zhí)行一遍就會創(chuàng)造一個新的函數(shù), 并且把函數(shù)地址賦值給 this.sayHi */ var o2 = new Person()
- 我們在使用構(gòu)造函數(shù)的時候, 可以通過一些帶啊嗎和內(nèi)容來向當(dāng)前的對象中添加一些內(nèi)容
- 我們得到的兩個對象里面都有自己的成員 name 和 age
- 我們在寫構(gòu)造函數(shù)的時候其實也可以添加一些方法進去
這樣也是可以的, 但是有一點小缺點
- 第一次 new 的時候, Person 這個函數(shù)要執(zhí)行一遍, 執(zhí)行一遍就會創(chuàng)造一個新的函數(shù), 并且把函數(shù)地址賦值給 this.sayHi
- 第二次 new 的時候, Person 這個函數(shù)要執(zhí)行一遍, 執(zhí)行一遍就會創(chuàng)造一個新的函數(shù), 并且把函數(shù)地址賦值給 this.sayHi
- 這樣寫的話, 我們兩個對象內(nèi)的
sayHi
函數(shù)就是一個代碼一模一樣, 功能一模一樣 - 但卻占用了兩個內(nèi)存空間
- 也就是說
o1.sayHi
是一個地址,o2.sayHi
是一個地址 - 所以我們執(zhí)行
console.log(o1.sayHi === o2.sayHi)
的到的結(jié)果是false
- 缺點: 一模一樣的函數(shù)出現(xiàn)了兩次, 占用了兩個空間地址
- 要想解決的話, 就需要一個東西, 叫做原型
原型
- 原型的出現(xiàn), 就是為了解決 構(gòu)造函數(shù)的缺點
- 也就是給我們提供了一個給對象添加函數(shù)的方法
- 不然構(gòu)造函數(shù)只能給對象添加屬性, 不能合理的添加函數(shù)就太 low 了
prototype
- 每一個函數(shù)天生自帶一個成員, 叫做 prototype, 是一個對象空間
- 既然每一個函數(shù)都有, 構(gòu)造函數(shù)也是函數(shù), 構(gòu)造函數(shù)也有這個對象空間
- 這個
prototype
對象空間可以由函數(shù)名來訪問
function Person () {} console.log(Person.prototype) // 是一個對象
- 既然是一個對象, 那么我們就可以向里面放入一些東西
function Person() {} Person.prototype.name = 'prototype' Person.prototype.sayHi = function () {}
- 重點: 在函數(shù)的 prototype 里存儲的內(nèi)容, 不是給函數(shù)使用的, 是給函數(shù)的每一個實例化對象使用的
proto
每一個對象都天生自帶一個成員, 叫做 __proto__
, 是一個對象空間
既然每一個對象都有, 實例化對象也是對象, 那么每一個實例化對象也有這個成員
這個 __proto__
對象空間是給每一個對象使用的
當(dāng)你訪問一個對象中的成員的時候
- 如果這個對象自己本身有這個成員, 那么就會直接給你結(jié)果
- 如果沒有, 就回去
__proto__
這個對象空間里面找, 里面有的話就會有結(jié)果 - 未完待續(xù)...
那么這個 __proto__
又指向哪里呢?
- 這個對象是由那個構(gòu)造函數(shù) new 出來的
- 那么這個對象的
__proto__
就指向這個構(gòu)造函數(shù)的prototype
function Person() {} var p1 = new Person() console.log(p1.__proto__ === Person.prototype) // true
實例化對象的 __proto__
和所屬構(gòu)造函數(shù)的 prototype
是一個對象空間
我們可以通過構(gòu)造函數(shù)名稱來向 prototype
中添加成員
對象在訪問的時候自己沒有, 可以自動去自己的 __proto__
中查找
那么, 我們之前構(gòu)造函數(shù)的缺點就可以解決了
- 我們可以把函數(shù)放在構(gòu)造函數(shù)的
prototype
中 - 實例化對象訪問的時候, 自己沒有, 就會自動去
__proto__
中找 - 那么也可以使用了
function Person() {} Person.prototype.sayHi = function () { console.log('hello Person') } var p1 = new Person() p1.sayHi()
p1
自己沒有sayHi
方法,就會去自己的__proto__
中查找p1.__proto__
就是Person.prototype
- 我們又向
Person.prototype
中添加了sayHi
方法 - 所以
p1.sayHi
就可以執(zhí)行了 - 到這里,當(dāng)我們實例化多個對象的時候,每個對象里面都沒有方法
- 都是去所屬的構(gòu)造函數(shù)的
prototype
中查找 - 那么每一個對象使用的函數(shù),其實都是同一個函數(shù)
- 那么就解決了我們構(gòu)造函數(shù)的缺點
function Person() {} Person.prototype.sayHi = function () { console.log('hello') } var p1 = new Person() var p2 = new Person() console.log(p1.sayHi === p2.sayHi)
p1
是Person
的一個實例p2
是Person
的一個實例- 也就是說
p1.__proto__
和p2.__proto__
指向的都是Person.prototype
- 當(dāng)
p1
去調(diào)用sayHi
方法的時候是去Person.prototype
中找 - 當(dāng)
p2
去調(diào)用sayHi
方法的時候是去Person.prototype
中找 - 那么兩個實例化對象就是找到的一個方法,也是執(zhí)行的一個方法
結(jié)論
- 當(dāng)我們寫構(gòu)造函數(shù)的時候
- 屬性我們直接寫在構(gòu)造函數(shù)體內(nèi)
- 方法我們寫在原型上
原型鏈
- 構(gòu)造函數(shù)的
prototype
是一個對象, 每一個對象又自帶__proto__
屬性 - 構(gòu)造函數(shù)的 prototype 里面的 proto 屬性又指向哪里?
一個對象所屬的構(gòu)造函數(shù)
每一個對象都有一個自己所屬的構(gòu)造函數(shù)
比如: 數(shù)組
// 數(shù)組本身也是一個對象 var arr = [] var arr1 = new Array()
- 以上兩種方式都是創(chuàng)造一個數(shù)組
- 我們就說數(shù)組所屬的構(gòu)造函數(shù)就是
Array
比如: 函數(shù)
// 函數(shù)本身也是一個對象 var fn = function () {} var fun = new Function()
- 以上兩種方式都是創(chuàng)造一個函數(shù)
- 我們就說函數(shù)所屬的構(gòu)造函數(shù)就是
Function
constructor
- 對象的
__proto__
里面也有一個成員叫做 constructor - 這個屬性就是指向當(dāng)前這個對象所屬的工造函數(shù)
鏈狀結(jié)構(gòu)
- 當(dāng)一個對象我們不知道準(zhǔn)確的是誰構(gòu)造的時候, 我們就把他看成
Object
的實例化對象 - 也就是說, 我們的 構(gòu)造函數(shù) 的 prototype 的 proto 指向的是 Object.prototype
Object.prototype
也是個對象, 那么它的__proto__
又指向誰呢?- 因為
Object
的 js 中的頂級構(gòu)造函數(shù), 我們有一句話叫 萬物皆對象 - 所以
Object.prototype
就到頂了,Object.prototype 的 __proto__
就是 null
原型鏈的訪問原則
- 訪問一個對象的成員時, 自己沒有就會去
__proto__
中找 - 接下來就是, 如果
__proto__
里沒有就再去__proto__
里面找 - 一直找到
Object.prototype
里面都沒有, 那么就會返回undefined
對象的賦值
到這里, 我們就會覺得, 如果是賦值的話, 那么也會按照原型鏈的規(guī)則來
但是: 并不是! 并不是! 并不是! 重要的事情說三遍
賦值的時候就是直接給對象本身賦值
- 如果原先有就是修改
- 如果原先沒有就是添加
- 不會和
__proto__
有關(guān)系
總結(jié)
到了這里, 我們就發(fā)現(xiàn)了面向?qū)ο蟮乃枷肽J?/p>
- 當(dāng)我想完成一個功能的時候
- 先看內(nèi)置構(gòu)造函數(shù)有沒有能給我提供一個完整功能對象的能力
- 如果沒有, 我們就自己寫一個構(gòu)造函數(shù), 能創(chuàng)造出一個完成功能的對象
- 然后再用我們寫的構(gòu)造函數(shù) new 一個對象出來, 幫助我們完成功能就行了
以上就是前端面向?qū)ο缶幊讨瓻S5語法ES6語法詳解的詳細內(nèi)容,更多關(guān)于前端面向?qū)ο缶幊蘀S5ES6語法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序基于高德地圖API實現(xiàn)天氣組件(動態(tài)效果)
這篇文章主要介紹了微信小程序基于高德地圖API實現(xiàn)天氣組件(動態(tài)效果),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10firefox中用javascript實現(xiàn)鼠標(biāo)位置的定位
firefox中用javascript實現(xiàn)鼠標(biāo)位置的定位...2007-06-06uniapp使用mui-player插件播放m3u8/flv視頻流示例代碼
在小程序里播放視頻是很常見的功能,下面這篇文章主要給大家介紹了關(guān)于uniapp使用mui-player插件播放m3u8/flv視頻流的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-06-06bootstrap table實現(xiàn)點擊翻頁功能 可記錄上下頁選中的行
這篇文章主要介紹了bootstrap table實現(xiàn)點擊翻頁功能,可記錄上下頁選中的行,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09JavaScript設(shè)置FieldSet展開與收縮
JavaScript設(shè)置FieldSet展開與收縮實現(xiàn)代碼。2009-05-05JavaScript實現(xiàn)窮舉排列(permutation)算法謎題解答
這篇文章主要介紹了JavaScript實現(xiàn)窮舉排列(permutation)算法謎題解答,窮舉排列是指窮舉一個數(shù)組中各個元素的排列,需要的朋友可以參考下2014-12-12