前端面向?qū)ο缶幊讨瓻S5語(yǔ)法ES6語(yǔ)法詳解
一.面向?qū)ο缶幊?/h2>
1.概念
- 通過(guò)對(duì)于具有相同屬性和函數(shù)方法的一類(lèi)事物的描述,實(shí)現(xiàn)代碼功能
- 對(duì)于具有相同屬性和函數(shù)方法的抽象類(lèi)實(shí)現(xiàn)代碼功能
2.理解
定義一個(gè)對(duì)象
利用對(duì)象的屬性存儲(chǔ)的數(shù)據(jù)
將程序執(zhí)行需要的數(shù)據(jù)都以屬性的形式,存儲(chǔ)在對(duì)象中
利用函數(shù)方法存儲(chǔ)程序代碼
將執(zhí)行程序需要的代碼
以函數(shù)方法的形式存儲(chǔ)
調(diào)用執(zhí)行函數(shù)方法時(shí)
使用的數(shù)據(jù)是對(duì)象屬性中存儲(chǔ)的數(shù)據(jù)
二.語(yǔ)法形式
工廠模式
function 函數(shù)(形參,形參...){
const obj= {};
//創(chuàng)建一個(gè)空對(duì)象
obj.屬性 = 屬性;
obj.屬性 = 屬性;
...
設(shè)定對(duì)象的屬性和屬性值
obj.函數(shù)方法 = function(){}
obj.函數(shù)方法 = function(){}
...
設(shè)定對(duì)象的函數(shù)方法
return obj;
返回值是這個(gè)創(chuàng)建的對(duì)象
}
/*
工廠模式 是 創(chuàng)建 屬性和函數(shù)方法相同
屬性值不同的 對(duì)象
創(chuàng)建的對(duì)象 都 相同的屬性 不同的屬性值
還有 完全相同的函數(shù)方法
每一個(gè)對(duì)象都存儲(chǔ)了完全相同的函數(shù)方法
造成有 冗余的代碼程序
*/
ES5語(yǔ)法
function 構(gòu)造函數(shù)(形參,形參...){
//在構(gòu)造函數(shù)中通過(guò)this指向設(shè)定操作對(duì)象的屬性
this.屬性 = 形參;
this.屬性 = 形參;
}
//在構(gòu)造函數(shù)外在構(gòu)造函數(shù)的prototype中定義函數(shù)
構(gòu)造函數(shù).prototype.函數(shù)方法 = function(){}
構(gòu)造函數(shù).prototype.函數(shù)方法 = function(){}
//通過(guò)new關(guān)鍵詞 調(diào)用構(gòu)造函數(shù)創(chuàng)建實(shí)例化對(duì)象
ES6語(yǔ)法
使用class關(guān)鍵詞定義構(gòu)造函數(shù)
class 構(gòu)造函數(shù){
//在構(gòu)造函數(shù)中定義對(duì)象的屬性屬性值
constructor(形參,形參...){
this.屬性 = 形參;
this.屬性 = 形參;
}
//在構(gòu)造函數(shù)外定義函數(shù)方法 js程序自動(dòng)定義在prototype 中
函數(shù)方法(){}
函數(shù)方法(){}
}
const 實(shí)例化對(duì)象 = new 構(gòu)造函數(shù)(實(shí)參,實(shí)參...);
通過(guò)new關(guān)鍵詞調(diào)用構(gòu)造函數(shù)創(chuàng)建實(shí)例化對(duì)象
三.批量生產(chǎn)對(duì)象
字面量方式
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. 手動(dòng)創(chuàng)建一個(gè)對(duì)象
const obj = {}
// 2. 手動(dòng)向?qū)ο髢?nèi)部添加屬性
obj.name = name
obj.age = age
// 3. 手動(dòng)返回一個(gè)對(duì)象
return obj
}
//這個(gè)方法能夠創(chuàng)建對(duì)象, 并且批量生產(chǎn)也可以
自定義構(gòu)造函數(shù)
function createObj () {
// 1. 自動(dòng)創(chuàng)建出來(lái)一個(gè)對(duì)象
// 2. 手動(dòng)向?qū)ο筇砑訉傩?
// 3. 自動(dòng)返回一個(gè)對(duì)象
}
const o1 = new createObj() // 這種調(diào)用方式, 才是 構(gòu)造函數(shù)
const o2 = createObj() // 這就是一個(gè)普通函數(shù)的調(diào)用
console.log(o1)
console.log(o2)
/*
自定義構(gòu)造函數(shù), 本質(zhì)是就是一個(gè)函數(shù)
當(dāng)他和 new 關(guān)鍵字連用的時(shí)候, 就叫做構(gòu)造函數(shù)
自動(dòng)創(chuàng)建一個(gè)對(duì)象
手動(dòng)向創(chuàng)建的對(duì)象添加屬性
自動(dòng)返回一個(gè)對(duì)象
*/
四.自定義構(gòu)造函數(shù)的書(shū)寫(xiě)
1. 一定是和new關(guān)鍵字連用
如果沒(méi)有和new連用,那么它就是一個(gè)普通函數(shù)
2.當(dāng)一個(gè)函數(shù)和new關(guān)鍵連用的時(shí)候,這個(gè)函數(shù)就被稱(chēng)為自定義構(gòu)造函數(shù),這個(gè)函數(shù)內(nèi)容this指向,指向返回出來(lái)的對(duì)象
3.構(gòu)造函數(shù)不能使用給箭頭函數(shù)
因?yàn)榧^函數(shù)內(nèi)部沒(méi)有this
4.構(gòu)造函數(shù)內(nèi)部不需要return
- return了基本數(shù)據(jù)類(lèi)型,寫(xiě)了和沒(méi)寫(xiě)一樣
- return 了引用數(shù)據(jù)類(lèi)型,寫(xiě)了構(gòu)造函數(shù)就沒(méi)用了
5.書(shū)寫(xiě)構(gòu)造函數(shù)時(shí),首字母建議大寫(xiě)
目的: 僅僅是為了和普通函數(shù)區(qū)分
6.我們構(gòu)造函數(shù)通過(guò)new關(guān)鍵字創(chuàng)建出來(lái)的對(duì)象,叫做實(shí)例化對(duì)象,本質(zhì)上還是一個(gè)對(duì)象,只不過(guò)名字上叫做實(shí)例化對(duì)象(實(shí)例對(duì)象)
我們把構(gòu)造函數(shù)通過(guò)new關(guān)鍵字創(chuàng)建對(duì)象的過(guò)程叫實(shí)例化
和普通函數(shù)一樣, 只不過(guò) 調(diào)用的時(shí)候要和 new 連用 不然就是一個(gè)普通函數(shù)調(diào)用
1.不寫(xiě)new的時(shí)候就是普通函數(shù)調(diào)用,沒(méi)有創(chuàng)造對(duì)象的能力
function Person () {}
var o1 = new Person() // 一個(gè)對(duì)象
var o2 = Person() // 什么也得不到, 就是一個(gè)普通函數(shù)的調(diào)用
2.首字母不大些, 只要和 new 連用, 就有創(chuàng)造對(duì)象的能力
function person () {}
var o1 = new person() // 一個(gè)對(duì)象
3.當(dāng)調(diào)用的時(shí)候, 如果不需要傳遞參數(shù)可以不寫(xiě) (), 但是建議寫(xiě)上
function person () {}
var o1 = new person // 一個(gè)對(duì)象
5.構(gòu)造函數(shù)內(nèi)部的 this, 由于和 new 連用的關(guān)系, 是指向當(dāng)前實(shí)例對(duì)象的
function Person () {
console.log(this)
}
var o1 = new Person() // this ---> o1
var o2 = new Person() // this ---> o2
五.使用構(gòu)造函數(shù)創(chuàng)建一個(gè)對(duì)象
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()
// 有缺點(diǎn)
function Person() {
this.name = 'Jack'
this.age = 18
this.sayHi = function () {
console.log('hello word')
}
}
/**
* 第一次 new 的時(shí)候, Person 這個(gè)函數(shù)要執(zhí)行一遍
* 執(zhí)行一邊就會(huì)創(chuàng)造一個(gè)新的函數(shù), 并且把函數(shù)地址賦值給 this.sayHi
*/
var o1 = new Person()
/**
* 第二次 new 的時(shí)候, Person 這個(gè)函數(shù)要執(zhí)行一遍
* 執(zhí)行一遍就會(huì)創(chuàng)造一個(gè)新的函數(shù), 并且把函數(shù)地址賦值給 this.sayHi
*/
var o2 = new Person()
- 我們?cè)谑褂脴?gòu)造函數(shù)的時(shí)候, 可以通過(guò)一些帶啊嗎和內(nèi)容來(lái)向當(dāng)前的對(duì)象中添加一些內(nèi)容
- 我們得到的兩個(gè)對(duì)象里面都有自己的成員 name 和 age
- 我們?cè)趯?xiě)構(gòu)造函數(shù)的時(shí)候其實(shí)也可以添加一些方法進(jìn)去
這樣也是可以的, 但是有一點(diǎn)小缺點(diǎn)
- 第一次 new 的時(shí)候, Person 這個(gè)函數(shù)要執(zhí)行一遍, 執(zhí)行一遍就會(huì)創(chuàng)造一個(gè)新的函數(shù), 并且把函數(shù)地址賦值給 this.sayHi
- 第二次 new 的時(shí)候, Person 這個(gè)函數(shù)要執(zhí)行一遍, 執(zhí)行一遍就會(huì)創(chuàng)造一個(gè)新的函數(shù), 并且把函數(shù)地址賦值給 this.sayHi
- 這樣寫(xiě)的話, 我們兩個(gè)對(duì)象內(nèi)的
sayHi函數(shù)就是一個(gè)代碼一模一樣, 功能一模一樣 - 但卻占用了兩個(gè)內(nèi)存空間
- 也就是說(shuō)
o1.sayHi是一個(gè)地址,o2.sayHi是一個(gè)地址 - 所以我們執(zhí)行
console.log(o1.sayHi === o2.sayHi)的到的結(jié)果是false - 缺點(diǎn): 一模一樣的函數(shù)出現(xiàn)了兩次, 占用了兩個(gè)空間地址
- 要想解決的話, 就需要一個(gè)東西, 叫做原型
原型
- 原型的出現(xiàn), 就是為了解決 構(gòu)造函數(shù)的缺點(diǎn)
- 也就是給我們提供了一個(gè)給對(duì)象添加函數(shù)的方法
- 不然構(gòu)造函數(shù)只能給對(duì)象添加屬性, 不能合理的添加函數(shù)就太 low 了
prototype
- 每一個(gè)函數(shù)天生自帶一個(gè)成員, 叫做 prototype, 是一個(gè)對(duì)象空間
- 既然每一個(gè)函數(shù)都有, 構(gòu)造函數(shù)也是函數(shù), 構(gòu)造函數(shù)也有這個(gè)對(duì)象空間
- 這個(gè)
prototype對(duì)象空間可以由函數(shù)名來(lái)訪問(wèn)
function Person () {}
console.log(Person.prototype) // 是一個(gè)對(duì)象
- 既然是一個(gè)對(duì)象, 那么我們就可以向里面放入一些東西
function Person() {}
Person.prototype.name = 'prototype'
Person.prototype.sayHi = function () {}
- 重點(diǎn): 在函數(shù)的 prototype 里存儲(chǔ)的內(nèi)容, 不是給函數(shù)使用的, 是給函數(shù)的每一個(gè)實(shí)例化對(duì)象使用的
proto
每一個(gè)對(duì)象都天生自帶一個(gè)成員, 叫做 __proto__, 是一個(gè)對(duì)象空間
既然每一個(gè)對(duì)象都有, 實(shí)例化對(duì)象也是對(duì)象, 那么每一個(gè)實(shí)例化對(duì)象也有這個(gè)成員
這個(gè) __proto__ 對(duì)象空間是給每一個(gè)對(duì)象使用的
當(dāng)你訪問(wèn)一個(gè)對(duì)象中的成員的時(shí)候
- 如果這個(gè)對(duì)象自己本身有這個(gè)成員, 那么就會(huì)直接給你結(jié)果
- 如果沒(méi)有, 就回去
__proto__這個(gè)對(duì)象空間里面找, 里面有的話就會(huì)有結(jié)果 - 未完待續(xù)...
那么這個(gè) __proto__ 又指向哪里呢?
- 這個(gè)對(duì)象是由那個(gè)構(gòu)造函數(shù) new 出來(lái)的
- 那么這個(gè)對(duì)象的
__proto__就指向這個(gè)構(gòu)造函數(shù)的prototype
function Person() {}
var p1 = new Person()
console.log(p1.__proto__ === Person.prototype) // true
實(shí)例化對(duì)象的 __proto__ 和所屬構(gòu)造函數(shù)的 prototype 是一個(gè)對(duì)象空間
我們可以通過(guò)構(gòu)造函數(shù)名稱(chēng)來(lái)向 prototype 中添加成員
對(duì)象在訪問(wèn)的時(shí)候自己沒(méi)有, 可以自動(dòng)去自己的 __proto__ 中查找
那么, 我們之前構(gòu)造函數(shù)的缺點(diǎn)就可以解決了
- 我們可以把函數(shù)放在構(gòu)造函數(shù)的
prototype中 - 實(shí)例化對(duì)象訪問(wèn)的時(shí)候, 自己沒(méi)有, 就會(huì)自動(dòng)去
__proto__中找 - 那么也可以使用了
function Person() {}
Person.prototype.sayHi = function () {
console.log('hello Person')
}
var p1 = new Person()
p1.sayHi()
p1自己沒(méi)有sayHi方法,就會(huì)去自己的__proto__中查找p1.__proto__就是Person.prototype- 我們又向
Person.prototype中添加了sayHi方法 - 所以
p1.sayHi就可以執(zhí)行了 - 到這里,當(dāng)我們實(shí)例化多個(gè)對(duì)象的時(shí)候,每個(gè)對(duì)象里面都沒(méi)有方法
- 都是去所屬的構(gòu)造函數(shù)的
prototype中查找 - 那么每一個(gè)對(duì)象使用的函數(shù),其實(shí)都是同一個(gè)函數(shù)
- 那么就解決了我們構(gòu)造函數(shù)的缺點(diǎn)
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的一個(gè)實(shí)例p2是Person的一個(gè)實(shí)例- 也就是說(shuō)
p1.__proto__和p2.__proto__指向的都是Person.prototype - 當(dāng)
p1去調(diào)用sayHi方法的時(shí)候是去Person.prototype中找 - 當(dāng)
p2去調(diào)用sayHi方法的時(shí)候是去Person.prototype中找 - 那么兩個(gè)實(shí)例化對(duì)象就是找到的一個(gè)方法,也是執(zhí)行的一個(gè)方法
結(jié)論
- 當(dāng)我們寫(xiě)構(gòu)造函數(shù)的時(shí)候
- 屬性我們直接寫(xiě)在構(gòu)造函數(shù)體內(nèi)
- 方法我們寫(xiě)在原型上
原型鏈
- 構(gòu)造函數(shù)的
prototype是一個(gè)對(duì)象, 每一個(gè)對(duì)象又自帶__proto__屬性 - 構(gòu)造函數(shù)的 prototype 里面的 proto 屬性又指向哪里?
一個(gè)對(duì)象所屬的構(gòu)造函數(shù)
每一個(gè)對(duì)象都有一個(gè)自己所屬的構(gòu)造函數(shù)
比如: 數(shù)組
// 數(shù)組本身也是一個(gè)對(duì)象 var arr = [] var arr1 = new Array()
- 以上兩種方式都是創(chuàng)造一個(gè)數(shù)組
- 我們就說(shuō)數(shù)組所屬的構(gòu)造函數(shù)就是
Array
比如: 函數(shù)
// 函數(shù)本身也是一個(gè)對(duì)象
var fn = function () {}
var fun = new Function()
- 以上兩種方式都是創(chuàng)造一個(gè)函數(shù)
- 我們就說(shuō)函數(shù)所屬的構(gòu)造函數(shù)就是
Function
constructor
- 對(duì)象的
__proto__里面也有一個(gè)成員叫做 constructor - 這個(gè)屬性就是指向當(dāng)前這個(gè)對(duì)象所屬的工造函數(shù)
鏈狀結(jié)構(gòu)
- 當(dāng)一個(gè)對(duì)象我們不知道準(zhǔn)確的是誰(shuí)構(gòu)造的時(shí)候, 我們就把他看成
Object的實(shí)例化對(duì)象 - 也就是說(shuō), 我們的 構(gòu)造函數(shù) 的 prototype 的 proto 指向的是 Object.prototype
Object.prototype也是個(gè)對(duì)象, 那么它的__proto__又指向誰(shuí)呢?- 因?yàn)?
Object的 js 中的頂級(jí)構(gòu)造函數(shù), 我們有一句話叫 萬(wàn)物皆對(duì)象 - 所以
Object.prototype就到頂了,Object.prototype 的 __proto__就是 null
原型鏈的訪問(wèn)原則
- 訪問(wèn)一個(gè)對(duì)象的成員時(shí), 自己沒(méi)有就會(huì)去
__proto__中找 - 接下來(lái)就是, 如果
__proto__里沒(méi)有就再去__proto__里面找 - 一直找到
Object.prototype里面都沒(méi)有, 那么就會(huì)返回undefined
對(duì)象的賦值
到這里, 我們就會(huì)覺(jué)得, 如果是賦值的話, 那么也會(huì)按照原型鏈的規(guī)則來(lái)
但是: 并不是! 并不是! 并不是! 重要的事情說(shuō)三遍
賦值的時(shí)候就是直接給對(duì)象本身賦值
- 如果原先有就是修改
- 如果原先沒(méi)有就是添加
- 不會(huì)和
__proto__有關(guān)系
總結(jié)
到了這里, 我們就發(fā)現(xiàn)了面向?qū)ο蟮乃枷肽J?/p>
- 當(dāng)我想完成一個(gè)功能的時(shí)候
- 先看內(nèi)置構(gòu)造函數(shù)有沒(méi)有能給我提供一個(gè)完整功能對(duì)象的能力
- 如果沒(méi)有, 我們就自己寫(xiě)一個(gè)構(gòu)造函數(shù), 能創(chuàng)造出一個(gè)完成功能的對(duì)象
- 然后再用我們寫(xiě)的構(gòu)造函數(shù) new 一個(gè)對(duì)象出來(lái), 幫助我們完成功能就行了
以上就是前端面向?qū)ο缶幊讨瓻S5語(yǔ)法ES6語(yǔ)法詳解的詳細(xì)內(nèi)容,更多關(guān)于前端面向?qū)ο缶幊蘀S5ES6語(yǔ)法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js如何準(zhǔn)確獲取當(dāng)前頁(yè)面url網(wǎng)址信息
這篇文章主要為大家介紹了js準(zhǔn)確獲取當(dāng)前頁(yè)面url網(wǎng)址信息的多種方法,包括正則法、split拆分法等,需要的朋友可以參考下2016-04-04
Javascript中3個(gè)需要注意的運(yùn)算符
這篇文章主要介紹了Javascript中3個(gè)需要注意的運(yùn)算符,這3個(gè)運(yùn)算符的使用有很多需要注意的地方和有意思的地方,需要的朋友可以參考下2015-04-04
讓html頁(yè)面不緩存js的實(shí)現(xiàn)方法
這篇文章主要介紹了讓html頁(yè)面不緩存js的實(shí)現(xiàn)方法,分析了HTML頁(yè)面緩存js的原理,并由此分析實(shí)現(xiàn)不緩存js的方法,是非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10
非常酷炫的Bootstrap圖片輪播動(dòng)畫(huà)
這篇文章主要為大家分享了非??犰诺腂ootstrap圖片輪播動(dòng)畫(huà),幾行jQuery和animate.css庫(kù)用在基本的Bootstrap輪播組件中,感興趣的小伙伴們可以參考一下2016-05-05
JavaScript中高級(jí)語(yǔ)法??表達(dá)式用法示例詳解
這篇文章主要為大家介紹了JavaScript中高級(jí)語(yǔ)法??表達(dá)式用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
localStorage的黑科技-js和css緩存機(jī)制
本文主要介紹了localStorage的黑科技-js和css緩存機(jī)制的相關(guān)知識(shí),具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02
web網(wǎng)頁(yè)按比例顯示圖片實(shí)現(xiàn)原理及js代碼
由于上傳圖片的大小是未知的,在顯示成縮略圖的時(shí)候必須進(jìn)行按比例的縮放才能美觀地顯示,本文將為大家簡(jiǎn)單的介紹一種比較不錯(cuò)的方法,有此需求的朋友可以參考下2013-08-08
前端進(jìn)行雙重身份驗(yàn)證的實(shí)現(xiàn)與思路詳解
在傳統(tǒng)的身份驗(yàn)證方案之上,雙重身份驗(yàn)證(Double?Token)作為一?種增強(qiáng)型認(rèn)證方法,逐漸成為現(xiàn)代前端應(yīng)用中的關(guān)鍵技術(shù),下面小編就來(lái)為大家詳細(xì)講講雙重身份驗(yàn)證的實(shí)現(xiàn)與思路吧2025-02-02

