js组装知识(待续……)
object.assign()
這個方法回使源對象上的[[Get]]取得屬性的值,然后使用目標對象上的[[Set]]設(shè)置屬性的值
實際上對每個源對象執(zhí)行的是淺復制,如果多個源對象都有相同的屬性,則使用最后一個賦值的值
Object.is()
和===很像,接收兩個參數(shù)
console.log(+0 === -0) //true console.log(+0 === 0) //true console.log(-0 === 0) //true // 判斷NaN console.log(NaN === NaN)//false console.log(isNaN(NaN))//true // 用object.is()輕松解決 console.log(Object.is(NaN, NaN))//true console.log(Object.is(+0, -0))//false // 要檢查超過兩個值,利用遞歸即可 function deep(x, ...rest) {// 傳入的值為 1,[1,1,4]; 1,[1,4] ; 1,[4]return Object.is(x, rest[0]) && (rest.length < 2 || deep(...rest)) } let a = deep(1, 1, 1, 4) console.log(a) //falsees6增強的對象語法
//1, 屬性名簡寫 let a = 1; let obj = {a}; console.log(obj) //{a:1} // 代碼壓縮程序會在不同的作用域間保留屬性名,以防找不到引用 ------這句話還不理解//2,可計算屬性 // 有了計算屬性,就可以在對象字面量中完成動態(tài)屬性賦值.中括號運算符包圍 //的對象屬性鍵告訴運行時將其作為JavaScript表達式而不是字符串來求職 // 例 const a = 'name'; const b = 'sex'; const c = 'age'; let obj = { [a]: '小紅', [b]: '女', [c]: 10 } console.log(obj) //{name:'小紅',sex:'女',age:10} // 當然[]里也可以是一個復雜的函數(shù)// 3,簡寫方法名 let obj = {// 舊的寫法oldName: function (a) {console.log(a)},//新的寫法newName(a) {console.log(a)} }解構(gòu)賦值
// 解構(gòu)在內(nèi)部使用ToObject()把源數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為對象。這也意味著 //在對象結(jié)構(gòu)的上下文中,原始值會被當成對象,這也意味著 // (根據(jù)ToObject()的定義),null和undefined不能被結(jié)構(gòu),否則會拋出錯誤。 // 例 let { length } = 'foobar'; let { constructor } = 'foobar' // // 這里一定要切記 源對象轉(zhuǎn)為對象就能看懂了 console.log(length, constructor) //6,? String() { [native code] } console.log(constructor === String) //true //嵌套結(jié)構(gòu) //解構(gòu)可以使用嵌套結(jié)構(gòu),以匹配嵌套的屬性: let obj = {name: '小明',age: 11,job: {title: 'web前端'} } let { job: { title } } = obj console.log(title) // web前端 // 參數(shù)解構(gòu)---對參數(shù)進行解構(gòu)不會影響arguments對象 let data = {b: 2, c: 3 } function aaa(a, { b, c }, d) {console.log(arguments) // 1,[2,3],4console.log(b, c) // 2,3 } aaa(1, data, 2)try catch 語句
如果try中的代碼沒有出錯,則程序正常運行try中的內(nèi)容后,不會執(zhí)行catch中的內(nèi)容,
如果try中的代碼一但出錯,程序立即跳入catch中去執(zhí)行代碼,那么try中出錯代碼后的
所有代碼就不再執(zhí)行了.
工廠函數(shù)
這種工廠模式雖然可以解決創(chuàng)建多個類似對象的問題,但沒有解
決對象標識問題(即新創(chuàng)建的對象是什么類型)
構(gòu)造函數(shù)
定義構(gòu)造函數(shù)可以確保實例被標識為特定類型
構(gòu)造函數(shù)也是函數(shù),和普通函數(shù)的唯一區(qū)別在于調(diào)用方式不同
構(gòu)造函數(shù)和工廠函數(shù)的區(qū)別
1、沒有明顯的創(chuàng)建對象
2、屬性和方法直接賦值給了this
3、沒有return
構(gòu)造函數(shù)需要注意的事項?
首字母大寫,有助于和普通函數(shù)進行區(qū)分。
要創(chuàng)建Person實例,需要使用new操作符,以這種方式調(diào)用構(gòu)造函數(shù)會進行如下操作。
1> 在內(nèi)存中創(chuàng)建一個新對象;
2> 這個新對象內(nèi)部的[[prototype]]特性被賦值為構(gòu)造函數(shù)的prototype屬性。
3> 構(gòu)造函數(shù)內(nèi)部的this被賦值為這個新對象(即this指向新對象)。
4> 執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼(給新對象添加屬性)
5> 如果構(gòu)造函數(shù)返回非空對象,則返回該對象;否則,返回剛創(chuàng)建的新對象。 ——————不太明白
原型模式
每個函數(shù)都會創(chuàng)建prototype屬性,這個屬性是一個對象,
包含應該由特定引用類型的實例共享的屬性和方法。
好處是 在它上面的屬性或方法可以被對象實例共享
高階函數(shù)
符合以下一個條件即可
- 若A函數(shù),接收到的參數(shù)是一個函數(shù),那么A就可以稱之為高階函數(shù)。
- 若A函數(shù),調(diào)用的返回值依然是一個函數(shù),那么A就可以稱之為高階函數(shù)
常見的有Promist setTimeout 、arr.map()……
函數(shù)的柯里化
通過函數(shù)調(diào)用繼續(xù)返回函數(shù)的方式,實現(xiàn)多次接收參數(shù)最后統(tǒng)一處理的函數(shù)編碼形式
例 :
純函數(shù)
- 一類特別的函數(shù):只要是同樣的輸入(實參),必定得到同樣的輸出(返回)
- 必須遵守以下一些約束
- 不得改寫數(shù)據(jù)
- 不會產(chǎn)生任何副作用,例如網(wǎng)絡(luò)請求,輸入和輸出設(shè)備
- 不能調(diào)用Date.now()或者Math.random()等不純的方法
nanoid(現(xiàn)在這放著,懶得開新的了)
- 安裝 yarn add nanoid
- 使用 import {nanoid} from ‘nanoid’;
- 語法 nanoid()即可生成隨機字符
instanceof
檢查實例的原型鏈中,是否包含指定構(gòu)造函數(shù)的原型
function Person(name) {this.name = name}const p1 = new Person('小紅');console.log(p1 instanceof Person) //trueconsole.log(p1 instanceof Object) //trueconsole.log(Person.prototype instanceof Object) //trueisPrototypeOf()
本質(zhì)上,會在傳入?yún)?shù)的[[prototype]]指向調(diào)用它的對象時返回true
function Person(name) {this.name = name}const p1 = new Person('小紅');const p2 = new Person('小明');console.log(Person.prototype.isPrototypeOf(p1)) //trueconsole.log(Person.prototype.isPrototypeOf(p2)) //trueObject.getPrototypeOf(obj)
可以方便的取得一個對象的原型。
function Person(name) {this.name = name}const p1 = new Person('小紅');console.log(Object.getPrototypeOf(p1)) //{constructor:f}console.log(Object.getPrototypeOf(p1)==Person.prototype) //trueObject.setPrototypeOf()
可以向?qū)嵗乃接袑傩訹[prototype]]寫入一個新值,這樣就可以重寫一個對象的原型繼承關(guān)系
【注意】這個方法可能會影響代碼性能,會涉及所有訪問了拿些修改過[[prototype]]的對象的代碼
Object.create()
來創(chuàng)建一個新對象,同時為其指定原型
let biped = { numLegs: 2 };let person = Object.create(biped)person.name = 'Matt';console.log(person.name); //'Matt'console.log(person.numLegs); //2console.log(Object.getPrototypeOf(person) === biped); //true原型層級
- 在通過對象訪問屬性時,會按照這個屬性的名稱開始搜索,搜索開始對象實例本身。
如果在這個實例上發(fā)現(xiàn)了給定的名稱,則返回該對象名稱對應的值 - 如果沒有找到屬性,則搜索會沿著指針進入原型對象,找到則返回該屬性對應的值,
這也就是原型用于在多個對象實例間共享屬性的原理。
【注意】通過實例讀取原型對象的值是不可更改的,如果在實例上添加一個與
原型對象同名的屬性,則會在實例上創(chuàng)建這個屬性,這樣會遮住原型對象的屬性
delect操作符
可以完全刪除實例上的屬性
function Person(name) {this.name = name;}let p1 = new Person('小紅');Person.prototype.name = '小明';console.log(p1.name) //'小紅'delete p1.name;console.log(p1.name) //'小明'hasOwnProperty()
檢測是否為實例屬性
function Person() {}let p1 = new Person();let p2 = new Person();Person.prototype.name = '小明';p1.name = '小紅';console.log(p1.hasOwnProperty('name')) //trueconsole.log(p2.hasOwnProperty('name')) //falseObject.getOwnPropertyDescriptor()
取得原型屬性的描述符(只對實例屬性有效)
function Person() {}let p1 = new Person();let p2 = new Person();Person.prototype.name = '小明';p1.name = '小紅';console.log(Object.getOwnPropertyDescriptor(p1, 'name')) //{value: "小紅", writable: true, enumerable: true, configurable: true}console.log(Object.getOwnPropertyDescriptor(p2, 'name')) //undefinedin操作符
function Person(name) {}let p1 = new Person();console.log('name' in p1) //falsep1.name = '小明'console.log('name' in p1) //truelet p2 = new Person();console.log('name' in p2) //falsePerson.prototype.name = '小紅'console.log('name' in p2) //true//結(jié)論,無論屬性在實例自身還是原型上都會返回true利用in和hasOwnProperty的特性實現(xiàn)檢測屬性是否存在于原型上
function detectionP(obj, k) {return !obj.hasOwnProperty(k) && ([k] in obj)}console.log(detectionP(p2, 'name'))for-in循環(huán)中使用in操作符時,可以通過對象訪問且可以被枚舉的屬性都會返回,
包括實例屬性和原型屬性
Object.keys()
接收一個對象作為參數(shù),返回包含該對象所有可枚舉屬性名稱的字符串數(shù)組
function Person(name) {this.name = name}let p1 = new Person('小紅');Object.defineProperties(p1, {"school": {value: 'bgs',enumerable: true //默認false},"class": {value: '1908'}})console.log(Object.keys(p1)) //['name']Object.getOwnPropertyNames()
只要是實例屬性(包含原型),無論是否可以枚舉,返回對象所有屬性名稱的字符串數(shù)組
function Person(name) {this.name = name}let k1 = Symbol('k1')let p1 = new Person('小紅');Object.defineProperties(p1, {"school": {value: 'bgs',enumerable: true //默認false},"class": {value: '1908'},[k1]: {value: 1}})console.log(Object.getOwnPropertyNames(p1)) //["name", "school", "class"]Object.getOwnPropertySymbols()
只針對符號,類似getOwnPropertyNames
語法Object.getOwnPropertySymbols(obj)
屬性枚舉的順序
- for-in和Object.keys()的枚舉順序是不確定的,取決于javascript引擎,
可能因瀏覽器而異 - Object.getOwnPropertyName()、Object.getOwnPropertySymbols()
和object.assign()的枚舉順序是確定性的。 - 先以升序枚舉數(shù)值鍵,然后以插入順序枚舉字符串和符號鍵,
在對象字面量中定義的鍵以它們逗號分隔的順序插入。
ECMAScript2017新增兩個靜態(tài)方法
Object.values()
接收一個對象,返回對象值的數(shù)組(淺復制)
Object.entries()
接收一個對象,返回鍵值對數(shù)組(淺復制)。非字符串屬性會被轉(zhuǎn)換為字符串輸出,
符號屬性會被忽略
原型的語法
之前每次給原型上增加屬性都要通過Person.prototype.key=value
function Person() { }//錯誤的寫法1,會丟失constructor屬性Person.prototype = {name: '小紅',age: 10}const p1 = new Person()console.log(Person.prototype.constructor) //? Object() { [native code] }//錯誤的寫法2,這樣會得到一個[[Enumberable]]為true的constructor屬性Person.prototype = {constructor: Person,name: '小紅',age: 10}const p1 = new Person()console.log(p1.constructor) for (let k in p1) {console.log(k) //name,age,constructor}//正確的寫法Person.prototype = {name: '小紅',age: 10}Object.defineProperty(Person.prototype, 'constructor', {value: Person,enumerable: false})const p1 = new Person()for (let k in p1) {console.log(k) //name,age}實例只有指向原型的指針,沒有指向構(gòu)造函數(shù)的指針.
重寫構(gòu)造函數(shù)上的原型之后在創(chuàng)建的實例才會引用引得原型。而再次之前創(chuàng)建的實例仍然會引用最初的原型
toString()
方法可把一個 Number 對象轉(zhuǎn)換為一個字符串,并返回結(jié)果。
一個參數(shù):可以返回2~32進制的字符串
檢查數(shù)據(jù)類型
Object.prototype.toString.call()
繼承
原型鏈繼承的問題
- 主要問題出現(xiàn)在原型中包含引用值的時候(相同引用)
- 子類型在實例化時不能給父類型的構(gòu)造函數(shù)傳參
盜用構(gòu)造函數(shù)(也叫“經(jīng)典繼承”或“對象偽裝”)
使用apply()和call()方法以新創(chuàng)建的對象為上下文執(zhí)行構(gòu)造函數(shù)
缺點不能訪問父類原型上定義的方法
組合繼承
就是綜合了原型鏈和盜用構(gòu)造函數(shù),將兩者的優(yōu)點結(jié)合。
基本思路就是使用原型鏈繼承原型上的屬性和方法,而通過盜用構(gòu)造函數(shù)繼承實例屬性
調(diào)用過程中會執(zhí)行兩次SuperType函數(shù)
寄生式組合繼承(效果最佳) (紅寶石248頁)
只會調(diào)用一次SuperType函數(shù)
總結(jié)
以上是生活随笔為你收集整理的js组装知识(待续……)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kafka精华问答 | kafka的使
- 下一篇: 怎么制作u盘xp启动盘 制作U盘XP启动