事件循環(huán)機(jī)制
同步:執(zhí)行棧
異步:任務(wù)隊(duì)列
1.宏任務(wù)
- 點(diǎn)擊回調(diào)
- settimeout
2.微任務(wù)
- 當(dāng)前task執(zhí)行結(jié)束后立即執(zhí)行的任務(wù)
- 新微任務(wù)將放到隊(duì)列尾部
- promise
微任務(wù)會(huì)在下一個(gè)宏任務(wù)前,全部執(zhí)行完
3.事件隊(duì)列
同步任務(wù) → 主線(xiàn)程(執(zhí)行棧)→ 執(zhí)行完成 → 任務(wù)隊(duì)列
瀏覽器渲染
- 處理 HTML 標(biāo)記并構(gòu)建 DOM 樹(shù)。
- 處理 CSS 標(biāo)記并構(gòu)建 CSSOM(Style Rules) 樹(shù)。
- 將 DOM 與 CSSOM 合并成一個(gè)渲染樹(shù)(Render Tree)。
- 根據(jù)渲染樹(shù)(Layout)來(lái)布局,以計(jì)算每個(gè)節(jié)點(diǎn)的幾何信息。
- 將各個(gè)節(jié)點(diǎn)繪制(Painting)到屏幕上
深拷貝&淺拷貝
- 首先可以通過(guò) Object.assign 來(lái)解決這個(gè)問(wèn)題,很多人認(rèn)為這個(gè)函數(shù)是用來(lái)深拷貝的。其實(shí)并不是,Object.assign 只會(huì)拷貝所有的屬性值到新的對(duì)象中,如果屬性值是對(duì)象的話(huà),拷貝的是地址,所以并不是深拷貝。 淺拷貝就只是拷貝的對(duì)象的地址。
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
- 另外我們還可以通過(guò)展開(kāi)運(yùn)算符 ... 來(lái)實(shí)現(xiàn)淺拷貝
let a = {
age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1
解構(gòu)賦值的拷貝是淺拷貝,不能復(fù)制繼承自原型對(duì)象的屬性。
- 深拷貝 這個(gè)問(wèn)題通??梢酝ㄟ^(guò) JSON.parse(JSON.stringify(object)) 來(lái)解決。
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
但是該方法也是有局限性的:
- 會(huì)忽略 undefined
- 會(huì)忽略 symbol
- 不能序列化函數(shù)
- 不能解決循環(huán)引用的對(duì)象
關(guān)于枚舉
四個(gè)操作會(huì)忽略enumerable為false的屬性。
- for...in循環(huán):只遍歷對(duì)象自身的和繼承的可枚舉的屬性。含原型鏈
- Object.keys():返回對(duì)象自身的所有可枚舉的屬性的鍵名。含原型鏈
- JSON.stringify():只串行化對(duì)象自身的可枚舉的屬性。
- Object.assign(): 忽略enumerable為false的屬性,只拷貝對(duì)象自身的可枚舉的屬性。
屬性的遍歷
ES6 一共有 5 種方法可以遍歷對(duì)象的屬性。
- (1)for...in
for...in循環(huán)遍歷對(duì)象自身的和繼承的可枚舉屬性(不含 Symbol 屬性)。
- (2)Object.keys(obj)
Object.keys返回一個(gè)數(shù)組,包括對(duì)象自身的(不含繼承的)所有可枚舉屬性(不含 Symbol 屬性)的鍵名。
- (3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一個(gè)數(shù)組,包含對(duì)象自身的所有屬性(不含 Symbol 屬性,但是包括不可枚舉屬性)的鍵名。
(4)object.getOwnPropertySymbols返回一個(gè)數(shù)組,包含對(duì)象自身的所有 Symbol 屬性的鍵名。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys()返回一個(gè)包含所有自身屬性(不包含繼承屬性)的數(shù)組。(類(lèi)似于 Object.keys(), 但不會(huì)受enumerable影響).
js原型
1、proto ( [[Prototype]] )
對(duì)象原型鏈,可以直接通過(guò)屬性訪(fǎng)問(wèn);如果屬性不在當(dāng)前對(duì)象中,就通過(guò)原型鏈查找
var anotherObject = { a:2 };
//自行了解 Object.create(..) 的原理,現(xiàn)在只需要知道它會(huì)創(chuàng)建一個(gè)
對(duì)象并把這個(gè)對(duì)象的 [[Prototype]] 關(guān)聯(lián)到指定的對(duì)象。
var myObject = Object.create( anotherObject );
myObject.a; // 2
myObject.__proto__ === anotherObject //true;
所有普通的 [[Prototype]] 鏈最終都會(huì)指向內(nèi)置的 Object.prototype
都是Object實(shí)例出來(lái)的;
anotherObject 改變 myObject.a改變
myObject.a 改變后,脫離anotherObject
myObject.hasOwnProperty( "a" ); // true
**myObject.foo 總是會(huì)選擇原型鏈中最底層的 foo 屬性 **
2、prototype
所有的函數(shù)默認(rèn)都會(huì)擁有一個(gè) 名為prototyp的公有并且不可枚舉的屬性,它會(huì)指向另一個(gè)對(duì)象 ,這個(gè)對(duì)象通常被稱(chēng)為 Foo 的原型
function Foo() { // ...
}
var a = new Foo();
a.__proto__ === Foo.prototype// true;
new Foo() 只是間接完成了我們的目 標(biāo):一個(gè)關(guān)聯(lián)到其他對(duì)象的新對(duì)象。
3、constructor
function Foo() { // ... }
Foo.prototype.constructor === Foo; // true
//Foo.prototype 的 .constructor 屬性只是 Foo 函數(shù)在聲明時(shí)的默認(rèn)屬性。
如果 你創(chuàng)建了一個(gè)新對(duì)象并替換了函數(shù)默認(rèn)的 .prototype
對(duì)象引用,那么新對(duì)象并不會(huì)自動(dòng)獲 得 .constructor 屬性。
var a = new Foo();
a.constructor === Foo; // true
a.__proto__ === NothingSpecial.prototype //true;
a.constructor === Foo.prototype.constructor === Foo; // true
實(shí)際上 a 本身并沒(méi)有 .constructor 屬性。而且,雖然 a.constructor 確實(shí)指 向 Foo 函數(shù),但是這個(gè)屬性并不是表示 a 由 Foo“構(gòu)造”.
function NothingSpecial() { console.log( "Don't mind me!" ); }
var a = new NothingSpecial();
// "Don't mind me!" a;
// {}
小結(jié)
- Object 是所有對(duì)象的爸爸,所有對(duì)象都可以通過(guò)
__proto__找到它 - Function 是所有函數(shù)的爸爸,所有函數(shù)都可以通過(guò)
__proto__找到它 - 函數(shù)的
prototype是一個(gè)對(duì)象 - 對(duì)象的
__proto__屬性指向原型,__proto__將對(duì)象和原型連接起來(lái)組成了原型鏈
面向?qū)ο缶幊?/h3>
JavaScript不區(qū)分類(lèi)和實(shí)例的概念,而是通過(guò)原型(prototype)來(lái)實(shí)現(xiàn)面向?qū)ο缶幊獭?/p>
所有對(duì)象都是實(shí)例,所謂繼承關(guān)系不過(guò)是把一個(gè)對(duì)象的原型指向另一個(gè)對(duì)象而已。
Object.create()方法可以傳入一個(gè)原型對(duì)象,并創(chuàng)建一個(gè)基于該原型的新對(duì)象,但是新對(duì)象什么屬性都沒(méi)有,因此,我們可以編寫(xiě)一個(gè)函數(shù)來(lái)創(chuàng)建.
下一篇,框架篇中高級(jí)前端面試題(二)框架篇