從面向過程開發(fā)到面向對象開發(fā)练般,是個思維的重大轉變株扛,當真正理解了面向對象編程后揩环,對于日常的開發(fā)就會有一個質的飛躍鸟悴。
一. 面向過程與面向對象的區(qū)別
1.概念
1.面向過程
是一種以過程為中心的編程思想,面對問題耳胎,羅列出解決問題的步驟惯吕,然后按步驟一步步去實現(xiàn)
比如:蛋炒飯的制作,蛋和飯都混在一起废登,省事省力就能做出一盤美味可口的炒飯
2.面向對象
是以對象為核心郁惜,不需要關心程序內部的實現(xiàn)。解決問題時候,把問題抽象成對象羽戒,分析解決問題需要哪些對象缤沦,然后給對象里賦值一些方法和屬性,讓對象執(zhí)行自己的方法疚俱,解決問題缩多。
比如:蓋澆飯的制作呆奕,把一份完整的飯拆分成米飯和菜,通過組合不同的米粉和菜能滿足不同客戶定制化的需求
2.區(qū)別
1.面向過程:
優(yōu)點:性能較高
缺點:耦合性強衬吆,不易維護梁钾,擴展和復用
2.面向對象
優(yōu)點:程序間低耦合逊抡,易于維護,擴展和復用冒嫡,靈活配置
缺點:性能低于對象過程孝凌,因為面對對象需要實力化,比較消耗性能
二. 面向對象的特性
1.三大原則:封裝蟀架,繼承,多態(tài)
1.封裝
1.概念:也就是把客觀事物封裝成抽象的類煌集,并且類可以把自己的數(shù)據(jù)和方法只讓可信的類或者對象操作捌省,對不可信的進行信息隱藏。
封裝可以給用戶提供一個函數(shù)纲缓,函數(shù)里的方法屬性不對外暴漏,而能實現(xiàn)用戶想要實現(xiàn)的功能
好處:將變化隔離恭金,程序便于使用褂策,易于復用,安全性較高耿焊,
原則:隱藏不需要對外暴漏的屬性遍搞,僅提供公共訪問方式
2.繼承
1.概念:讓一個類擁有另一個類的屬性和方法
2.創(chuàng)建對象的方式
1.對象字面量
const obj = {}
2.構造函數(shù)
const = new Object()
3.Object.create()
用這種方式創(chuàng)建一個空對象 Object.create(Object.prototype),類似 {}溪猿,注意,Object.create(null)可以創(chuàng)建對象讲弄,但是這個對象沒有原型依痊,不會繼承任何東西,連toString()方法都沒有哦瓶摆。
const obj1 = {name:'111'}
const obj2 = Object.create(obj1)
console.log(obj2.name) // 111
2.繼承的方式
1.原型鏈
1.1 基本思想:利用原型性宏,讓一個引用類型繼承另一個引用類型的屬性和方法
// 父函數(shù)
function Parent(){
this.value1 = true
}
Parent.prototype.getParentValue = function(){
return this.value1
}
// 子類函數(shù)
function Child(){
this.value2 = false
}
// 這句話是最關鍵的。child 繼承了parent的原型
Child.prototype = new Parent()
Child.prototype.getChildvalue = function(){
return this.value2
}
const cc = new Child()
console.log(cc.getParentValue()) // true 這個是繼承的父類的方法
console.log(cc.getChildvalue()) // false 自己的方法
1.2 缺點:
缺點1.實例共享引用類型蝌借,
原型鏈繼承主要的問題是包含引用類型值的原型, 因為包含引用類型值的原型屬性會被所有的實例共享, 而在通過原型來實現(xiàn)繼承的時候, 原型實際變成了另外一個函數(shù)的實例(這里邊就有可能存在引用類型)
缺點2.在創(chuàng)建 Child 的子類的時候,無法像繼承元素傳遞參數(shù)
所以綜上指蚁,這種繼承方式少用
2.構造函數(shù)
3.組合繼承
4.原型式繼承
5.寄生式模式
6.寄生組合試繼承
3.多態(tài)
三. 對象的特性
1.對象的方法
1.1 屬性的簡潔方
const name='zy'
const obj = {name:name}
// 簡寫
const obj1 ={name}
console.log('obj1',obj1) // obj1: {name:'zy'}
1.2 屬性名表達式
const obj = {name:'zy'}
obj.name // 'zy'
obj['name'] // zy
1.3 屬性的可枚舉和遍歷 ***
1.可枚舉性
1. Object.getOwnPropertyDescriptor
每個屬性都有一個Descriptor凝化,方法是 Object.getOwnPropertyDescriptor(對象,屬性名)
const obj = {name:'zy'}
console.log(Object.getOwnPropertyDescriptor(obj,'name'))
// {
// configurable: true, // 是否可以刪除
// enumerable: true, // 是否可以枚舉
// value: zy,
// writable: true, // 是否可以編輯
// }
2.Object.getOwnPropertyDescriptors
若要看整個對象的描述搓劫,可以用Object.getOwnPropertyDescriptors(obj)
const obj = {name:'zy',age:'1'}
Object.getOwnPropertyDescriptors(obj)
// {
// age: {
// configurable: true,
// enumerable: true,
// value: "1",
// writable: true,
//}
//name: {
// configurable: true,
// enumerable: true,
// value: "zy",
// writable: true,
//}
//}
3.Object.defineProperty
這里可以看到通過對象字面量直接創(chuàng)建的屬性默認是可以遍歷,可以更改和可以刪除的勤揩,下面我們通過另一種方法創(chuàng)建對象的屬性秘蛔,Object.defineProperty
const obj = {}
Object.defineProperty(obj,'name',{
value:'zy'
})
console.log(obj) // {name:'zy}
console.log(Object.getOwnPropertyDescriptor(obj,'name'))
// {
// configurable: false
// enumerable: false
// value: 12
// writable: false,
// }
通過對比可以發(fā)現(xiàn)傍衡,直接字面量創(chuàng)建的對象屬性默認都是可以編輯遍歷和刪除的蛙埂,而通過Object.definePorperty創(chuàng)建的對象屬性則默認是不可編輯遍歷和刪除的遮糖。
擴展下 defineProperty的相關知識
configurable 是配置屬性是否可以刪除,默認true
enumerable 是配置屬性是否可以枚舉欲账,默認true
writable 是配置屬性是否可以編輯,默認true
4.Object.preventExtensions
Object.preventExtensions()方法讓一個對象變的不可擴展盼理,也就是永遠不能再添加新的屬性俄删。
1.通過對象字面量新增屬性,靜默的失敗
const obj = {name:'zy'}
Object.preventExtensions(obj)
obj.age = '1' //通過對象這種方式添加屬性已經(jīng)添加不上去了
console.log(obj) // {name:'zy'}
2.通過defineProperty給對象添加屬性則直接報錯
const obj = {name:'zy'}
Object.preventExtensions(obj)
Object.defineProperty(obj,'age',{value:'1'})
console.log(obj)
// Uncaught TypeError: Cannot define property age, object is not extensible
5.Object.isExtensible()
Object.isExtensible() 方法判斷一個對象是否是可擴展的(是否可以在它上面添加新的屬性)臊诊。
const obj = {name:'zy'}
Object.isExtensible(obj) // true
Object.preventExtensions(obj)
Object.isExtensible(obj) //false
6.Object.seal()
Object.seal()方法封閉一個對象斜脂,阻止添加新屬性并將所有現(xiàn)有屬性標記為不可配置。當前屬性的值只要原來是可寫的就可以改變玷或。
7.Object.freeze()
方法可以凍結一個對象片任。一個被凍結的對象再也不能被修改;凍結了一個對象則不能向這個對象添加新的屬性位他,不能刪除已有屬性产场,不能修改該對象已有屬性的可枚舉性、可配置性京景、可寫性,以及不能修改已有屬性的值醒串。此外,凍結一個對象后該對象的原型也不能被修改鼻吮。freeze() 返回和傳入的參數(shù)相同的對象较鼓。
2.遍歷
對象的遍歷總共有5種方式
1.for...in
for in可以遍歷對象自身和繼承的屬性违柏,不含不可枚舉和Symbol
補充個知識點:in 操作符 和 hasOwnProperty
in和hasOwnProperty的區(qū)別
in 可以檢查出自身和原型上的所有屬性
hasOwnProperty 判斷的自身的屬性
通過這兩個屬性可以區(qū)分是哪些屬性是自身的,哪些屬性是原型上的
const obj = {
name:'zy',
age:'1',
}
// in 操作符
console.log('name' in obj) // true 自身的屬性
console.log('age' in obj) // true 自身的屬性
console.log('wdith' in obj) // false 不存在這個屬性
console.log('toString' in obj) // true 原型上的方法
// hasOwnProperty
console.log(Object.hasOwnProperty('name')) // true 自身的屬性
console.log(Object.hasOwnProperty('toString')) // false 不是自身的屬性和方法
// 通過in 和 hasOwnProperty組合區(qū)分出原型的方法屬性
in 返回true hasOwnProperty 返回false的就是原型上的方法
function isPropertyItem(item,obj){
return item in obj && !Object.hasOwnProperty(item)
}
2.Object.keys(obj)
Object.keys,返回一個數(shù)組禽篱,可遍歷對象自身屬性馍惹,不含不可枚舉和Symbol
3.Object.getOwnpropertyNames(obj)
getOwnpropertyNames ,返回數(shù)組悼吱,獲取自身所有屬性良狈,包含不可枚舉,不含Symbol
4.Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols 返回數(shù)組薪丁,獲取自身所有Symbol屬性
5.Reflect.ownKeys(obj)
Reflect.ownKeys返回一個數(shù)組,獲取自身所有屬性严嗜,包含 不可枚舉和Symbol