
前言
這是讀書筆記第二篇,看完之后突然發(fā)現(xiàn)自己對(duì)js的內(nèi)置的一些東西還是了解的不夠全面,很多方法見都沒見過,啥用都不知道,這是非常不可取的。碼農(nóng)好歹也得眼熟啊,曉都不曉得后面的學(xué)習(xí)還怎么進(jìn)行下去。。。趕緊做筆記吧~文中如有錯(cuò)誤不當(dāng)不出,歡迎指出~
創(chuàng)建一個(gè)對(duì)象
var obj = {} //字面量創(chuàng)建
var obj = new Object() //構(gòu)造函數(shù)創(chuàng)建
2種創(chuàng)建方式是完全一樣的,一般書寫我們都采用字面量。
復(fù)制對(duì)象
首先明確一點(diǎn),借用紅寶書一句話,對(duì)于對(duì)于js中的賦值傳參等操作,傳遞的都是值,不關(guān)是基本類型還是引用類型,傳遞的都是值,只是引用類型傳遞的是一個(gè)內(nèi)存地址的值。不同對(duì)象如果引用同一塊內(nèi)存地址,還是會(huì)相互影響的。對(duì)象就是引用類型,這里介紹2種簡(jiǎn)單的方法來復(fù)制對(duì)象,又能不相互影響。
//安全的json序列對(duì)象,只能復(fù)制鍵值對(duì),不能復(fù)制函數(shù)
JSON.parse(JSON.stringify(obj))
//es6新增的內(nèi)置方法復(fù)制對(duì)象
Object.assign({},obj1,obj2...)
對(duì)象屬性的特性
一般我們看到的對(duì)象就是一對(duì)對(duì)鍵值對(duì),其實(shí)內(nèi)部并沒有我們想象的這么簡(jiǎn)單??匆韵麓a:
var a = {
a:2,
fuc:function() {
console.log('xxx')
}
}
//通過Object.getOwnPropertyDescriptors獲取對(duì)象屬性
Object.getOwnPropertyDescriptors(a)
a: {
configurable: true //可配置
enumerable: true //可枚舉
value: 2
writable: true // 可寫
}
.....
我們看到a屬性除了一個(gè)值外,還有3個(gè)默認(rèn)特性,繼續(xù)看:
var myObject = {};
Object.defineProperty( myObject, "a", {
value: 2,
writable: false, // not writable!
configurable: true,
enumerable: true
} );
myObject.a = 3;
myObject.a; // 2
通過Object.defineProperty定義了一個(gè)a屬性,該屬性不可寫,結(jié)果上我們已經(jīng)無(wú)法修改屬性值。
var myObject = {
a:2
};
myObject.a; // 2
delete myObject.a;
myObject.a; // undefined
Object.defineProperty( myObject, "a", {
value: 2,
writable: true,
configurable: false,
enumerable: true
} );
myObject.a; // 2
myObject.a = 5;
myObject.a; // 5
delete myObject.a;
myObject.a; // 5
設(shè)置屬性不可配置,我們看到我們無(wú)法再刪除這個(gè)屬性,但是仍然可以修改值。enumerable特性我們就比較熟悉了,for in循環(huán)枚舉屬性就是枚舉可枚舉的屬性,如果我們?cè)O(shè)置為false ,這個(gè)屬性就不會(huì)被枚舉。
要注意有一個(gè)小小的例外:即便屬性是configurable:false, 我們還是可以把writable的狀態(tài)由true改為false,但是無(wú)法由false改為true。
自定義屬性的set和get
var myObject = {
// 給 a 定義一個(gè)getter
get a() {
return this._a_;
},
// 給 a 定義一個(gè)setter
set a(val) {
this._a_ = val * 2;
}
};
myObject.a = 10 ;
myObject.a //20
上面代碼我們復(fù)寫了a屬性的獲取和設(shè)置方法,沒有賦值直接獲取會(huì)返回undefined,通過這個(gè)可以使我們創(chuàng)造出一些有趣的東西,vue源碼中我們就能看到很多實(shí)際的例子。
propertyIsEnumerable(..)會(huì)檢查給定的屬性名是否直接存在于對(duì)象中(而不是在原型鏈上)并且滿足enumerable:true。
Object.keys(..)會(huì)返回一個(gè)數(shù)組,包含所有可枚舉屬性,Object.getOwnPropertyNames(..)會(huì)返回一個(gè)數(shù)組,包含所有屬性,無(wú)論它們是否可枚舉。
in和hasOwnProperty(..)的區(qū)別在于是否查找[[Prototype]]鏈,然而,Object.keys(..)和Object.getOwnPropertyNames(..)都只會(huì)查找對(duì)象直接包含的屬性。
內(nèi)置方法這里不再贅述,實(shí)時(shí)了解ecmascript的動(dòng)態(tài),掌握新的內(nèi)容是非常必要的,我們可能永遠(yuǎn)用不到一些內(nèi)置方法,但是我們確保得先知道它,不然在需要的時(shí)候可能會(huì)像無(wú)頭蒼蠅亂撞或者使用一些比較蠢的老方法。
面向?qū)ο缶幊?/h2>
什么是面向?qū)ο缶幊??這個(gè)問題是我入坑時(shí)無(wú)法解惑的一個(gè)問題。但是隨著業(yè)務(wù)的不斷積累,這個(gè)問題會(huì)變得越來越清晰。
我們首先會(huì)介紹面向類的設(shè)計(jì)模式:實(shí)例化(instantiation)、繼承(inheritance)和(相對(duì))多態(tài)(polymorphism)。
類理論
類/繼承描述了一種代碼的組織結(jié)構(gòu)形式——一種在軟件中對(duì)真實(shí)世界中問題領(lǐng)域的建模方法。
面向?qū)ο缶幊虖?qiáng)調(diào)的是數(shù)據(jù)和操作數(shù)據(jù)的行為本質(zhì)上是互相關(guān)聯(lián)的(當(dāng)然,不同的數(shù)據(jù)有不同的行為),因此好的設(shè)計(jì)就是把數(shù)據(jù)以及和它相關(guān)的行為打包(或者說封裝)起來。這在正式的計(jì)算機(jī)科學(xué)中有時(shí)被稱為數(shù)據(jù)結(jié)構(gòu)。
舉例來說,用來表示一個(gè)單詞或者短語(yǔ)的一串字符通常被稱為字符串。字符就是數(shù)據(jù)。但是你關(guān)心的往往不是數(shù)據(jù)是什么,而是可以對(duì)數(shù)據(jù)做什么,所以可以應(yīng)用在這種數(shù)據(jù)上的行為(計(jì)算長(zhǎng)度、添加數(shù)據(jù)、搜索,等等)都被設(shè)計(jì)成String類的方法。
所有字符串都是String類的一個(gè)實(shí)例,也就是說它是一個(gè)包裹,包含字符數(shù)據(jù)和我們可以應(yīng)用在數(shù)據(jù)上的函數(shù)。
我們還可以使用類對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行分類,可以把任意數(shù)據(jù)結(jié)構(gòu)看作范圍更廣的定義的一種特例。
我們來看一個(gè)常見的例子,“汽車”可以被看作“交通工具”的一種特例,后者是更廣泛的類。
“在我們的軟件中,對(duì)不同的交通工具重復(fù)定義“載人能力”是沒有意義的。相反,我們只在Vehicle中定義一次,定義Car時(shí),只要聲明它繼承(或者擴(kuò)展)了Vehicle的這個(gè)基礎(chǔ)定義就行。Car的定義就是對(duì)通用Vehicle定義的特殊化。
雖然Vehicle和Car會(huì)定義相同的方法,但是實(shí)例中的數(shù)據(jù)可能是不同的,比如每輛車獨(dú)一無(wú)二的VIN(Vehicle Identification Number,車輛識(shí)別號(hào)碼),等等。
這就是類、繼承和實(shí)例化。
類的另一個(gè)核心概念是多態(tài),這個(gè)概念是說父類的通用行為可以被子類用更特殊的行為重寫。實(shí)際上,相對(duì)多態(tài)性允許我們從重寫行為中引用基礎(chǔ)行為。
'類'設(shè)計(jì)模式
你可能從來沒把類作為設(shè)計(jì)模式來看待,討論得最多的是面向?qū)ο笤O(shè)計(jì)模式,比如迭代器模式、觀察者模式、工廠模式、單例模式,等等。從這個(gè)角度來說,我們似乎是在(低級(jí))面向?qū)ο箢惖幕A(chǔ)上實(shí)現(xiàn)了所有(高級(jí))設(shè)計(jì)模式,似乎面向?qū)ο笫莾?yōu)秀代碼的基礎(chǔ)。
考慮到盡可能容易理解。這里摘錄了基本概念,這是一個(gè)抽象的東西,我們?cè)跀]碼過程中可能不知不覺就已經(jīng)在實(shí)踐這種理念,但是沒有看過這種概念的人可能會(huì)一下子說不出來。
這些概念實(shí)際上無(wú)法直接對(duì)應(yīng)到JavaScript的對(duì)象機(jī)制,因此JavaScript開發(fā)者用一系列方法去模擬實(shí)現(xiàn)面相編程,比如混入,mixin。
這里說說在下對(duì)面相對(duì)象編程的理解 ,面向?qū)ο缶幊唐鋵?shí)就是一類事物的抽象。比如 人,都會(huì)說話,走路,但是可能有的人說漢語(yǔ),有的人說英語(yǔ),對(duì)于這種廣泛的抽象中又有非常多的特例,我們可以對(duì)其建模:
var Person = function(){
this.name = 'person',
this.age = '',
this.talk = function(){alert('talk')},
this.walk = function(){alert('wall')}
}
var p1 = new Person()
var p2 = new Person()
p1.name = 'xu'
p2.name = 'pp'
...
我們構(gòu)造了一個(gè)person函數(shù),通過person函數(shù)構(gòu)造了2個(gè)人類實(shí)例,一個(gè)名字是xu一個(gè)名字是pp。。會(huì)說話,會(huì)走路。
ES6中的class語(yǔ)法
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
speak() {
console.log(this.name + ' barks.');
}
}
var d = new Dog('Mitzie');
// 'Mitzie barks.'
d.speak();
es6的class語(yǔ)法糖讓我們模擬面相編程變得更加規(guī)范,這里引用mdn的一個(gè)例子,更具體的建議可以自己找文章看,畢竟這是一個(gè)js一個(gè)非常重要的知識(shí)。
后記
要想完全搞懂一些概念,抽象的東西,其實(shí)并不是一天兩天,一兩篇文章就能做到的,我的建議是,理論,實(shí)踐,理論,實(shí)踐,一個(gè)螺旋上升的過程。感覺筆記內(nèi)容不是很深入,畢竟是讀書筆記和自己的一些理解看法,就當(dāng)深入的程度不是那么深吧~
如果覺得本文對(duì)你有所幫助,就star一下吧~大傳送之術(shù)! 我的博客Github