欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript三大重點(diǎn)同步異步與作用域和閉包及原型和原型鏈詳解

 更新時(shí)間:2022年07月25日 11:15:44   作者:大蓮芒  
這篇文章主要介紹了JavaScript同步異步與作用域和閉包及原型和原型鏈,每個(gè)對(duì)象都連接到一個(gè)原型對(duì)象,并且它可以從中繼承屬性。所有通過對(duì)象字面量創(chuàng)建的對(duì)象都連接到object.prototype,它是JavaScript中的標(biāo)配對(duì)象<BR>

如圖所示,JS的三座大山:

  • 同步、異步
  • 作用域、閉包
  • 原型、原型鏈

1. 同步、異步

JavaScript執(zhí)行機(jī)制,重點(diǎn)有兩點(diǎn):

  • JavaScript是一門單線程語言
  • Event Loop(事件循環(huán))是JavaScript的執(zhí)行機(jī)制

JS為什么是單線程

最初設(shè)計(jì)JS是用來在瀏覽器驗(yàn)證表單操控DOM元素的是一門腳本語言,如果js是多線程的,那么兩個(gè)線程同時(shí)對(duì)一個(gè)DOM元素進(jìn)行了相互沖突的操作,那么瀏覽器的解析器是無法執(zhí)行的。

js為什么需要異步

如果js中不存在異步,只能自上而下執(zhí)行,如果上一行解析時(shí)間很長(zhǎng),那么下面的代碼就會(huì)被阻塞。

對(duì)于用戶而言,阻塞就以為著“卡死”,這樣就導(dǎo)致了很差的用戶體驗(yàn)。比如在進(jìn)行ajax請(qǐng)求的時(shí)候如果沒有返回?cái)?shù)據(jù)后面的代碼就沒辦法執(zhí)行

JS的事件循環(huán)(eventloop)是怎么運(yùn)作的

  • 首先判斷JS是同步還是異步,同步就進(jìn)入主線程運(yùn)行,異步就進(jìn)入event table.
  • 異步任務(wù)在event table中注冊(cè)事件,當(dāng)滿足觸發(fā)條件后,(觸發(fā)條件可能是延時(shí)也可能是ajax回調(diào)),被推入event queue
  • 同步任務(wù)進(jìn)入主線程后一直執(zhí)行,直到主線程空閑時(shí),才會(huì)去event queue中查看是否有可執(zhí)行的異步任務(wù),如果有就推入主線程中。

如圖所示:

那怎么知道主線程執(zhí)行棧為空呢?js引擎存在monitoring process進(jìn)程,會(huì)持續(xù)不斷的檢查 主線程執(zhí)行棧是否為空,一旦為空,就會(huì)去event queue那里檢查是否有等待被調(diào)用的函數(shù)

宏任務(wù) 包含整個(gè)script代碼塊,setTimeout, setIntval

微任務(wù) Promise , process.nextTick

在劃分宏任務(wù)、微任務(wù)的時(shí)候并沒有提到async/ await的本質(zhì)就是Promise

setTimeout(function() {
    console.log('4')
})
new Promise(function(resolve) {
    console.log('1') // 同步任務(wù)
    resolve()
}).then(function() {
    console.log('3')
})
console.log('2')

執(zhí)行結(jié)果: 1-2-3-4
1. 這段代碼作為宏任務(wù),進(jìn)入主線程。
2. 先遇到setTimeout,那么將其回調(diào)函數(shù)注冊(cè)后分發(fā)到宏任務(wù)event queue.
3. 接下來遇到Promise, new Promise立即執(zhí)行,then函數(shù)分發(fā)到微任務(wù)event queue
4. 遇到console.log(), 立即執(zhí)行
5. 整體代碼script作為第一個(gè)宏任務(wù)執(zhí)行結(jié)束, 查看當(dāng)前有沒有可執(zhí)行的微任務(wù),執(zhí)行then的回調(diào)。(第一輪事件循環(huán)結(jié)束了,我們開始第二輪循環(huán))
6. 從宏任務(wù)的event queue開始,我們發(fā)現(xiàn)了宏任務(wù)event queue中setTimeout對(duì)應(yīng)的回調(diào)函數(shù),立即執(zhí)行。

console.log('1')
setTimeout(function() {
    console.log('2')
    process.nextTick(function() {
        console.log('3')
    })
    new Promise(function(resolve) {
        console.log('4')
        resolve()
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6')
})
new Promise(function(resolve) {
    console.log('7')
    resolve()
}).then(function() {
    console.log('8')
})
setTimeout(function() {
    console.log('9')
    process.nextTick(function() {
        console.log('10')
    })
    new Promise(function(resolve) {
        console.log('11')
        resolve()
    }).then(function() {
        console.log('12')
    })
})

1.整體script作為第一個(gè)宏任務(wù)進(jìn)入主線程,遇到console.log(1)輸出1

遇到setTimeout, 其回調(diào)函數(shù)被分發(fā)到宏任務(wù)event queue中。我們暫且記為setTimeout1
3.遇到process.nextTick(),其回調(diào)函數(shù)被分發(fā)到微任務(wù)event queue中,我們記為process1
4.遇到Promise, new Promise直接執(zhí)行,輸出7.then被分發(fā)到微任務(wù)event queue中,我們記為then1
又遇到setTimeout,其回調(diào)函數(shù)被分發(fā)到宏任務(wù)event queue中,我們記為setTimeout2.
現(xiàn)在開始執(zhí)行微任務(wù), 我們發(fā)現(xiàn)了process1和then1兩個(gè)微任務(wù),執(zhí)行process1,輸出6,執(zhí)行then1,輸出8, 第一輪事件循環(huán)正式結(jié)束, 這一輪的結(jié)果輸出1,7,6,8.那么第二輪事件循環(huán)從setTimeout1宏任務(wù)開始
5. 首先輸出2, 接下來遇到了process.nextTick(),統(tǒng)一被分發(fā)到微任務(wù)event queue,記為process2
8new Promise立即執(zhí)行,輸出4,then也被分發(fā)到微任務(wù)event queue中,記為then2
6. 現(xiàn)在開始執(zhí)行微任務(wù),我們發(fā)現(xiàn)有process2和then2兩個(gè)微任務(wù)可以執(zhí)行輸出3,5. 第二輪事件循環(huán)結(jié)束,第二輪輸出2,4,3,5. 第三輪事件循環(huán)從setTimeout2哄任務(wù)開始
10。 直接輸出9,跟第二輪事件循環(huán)類似,輸出9,11,10,12
7. 完整輸出是1,7,6,8,2,4,3,5,9,11,10,12(請(qǐng)注意,node環(huán)境下的事件監(jiān)聽依賴libuv與前端環(huán)境不完全相同,輸出順序可能會(huì)有誤差)

async/await用來干什么

用來優(yōu)化promise的回調(diào)問題,被稱為是異步的終極解決方案

async/await內(nèi)部做了什么

async函數(shù)會(huì)返回一個(gè)Promise對(duì)象,如果在函數(shù)中return一個(gè)直接量(普通變量),async會(huì)把這個(gè)直接量通過Promise.resolve()封裝成Promise對(duì)象。如果你返回了promise那就以你返回的promise為準(zhǔn)。await是在等待,等待運(yùn)行的結(jié)果也就是返回值。await后面通常是一個(gè)異步操作(promise),但是這不代表await后面只能跟異步才做,await后面實(shí)際是可以接普通函數(shù)調(diào)用或者直接量。

async相當(dāng)于 new Promise,await相當(dāng)于then

await的等待機(jī)制

如果await后面跟的不是一個(gè)promise,那await后面表達(dá)式的運(yùn)算結(jié)果就是它等到的東西,如果await后面跟的是一個(gè)promise對(duì)象,await它會(huì)’阻塞’后面的diamante,等著promise對(duì)象resolve,

然后得到resolve的值作為await表達(dá)式的運(yùn)算結(jié)果。但是此"阻塞"非彼“阻塞”,這就是await必須用在async函數(shù)中的原因。 async函數(shù)調(diào)用不會(huì)造成"阻塞",它內(nèi)部所有的“阻塞”都被封裝在一個(gè)promise對(duì)象中異步執(zhí)行(這里的阻塞理解成異步等待更合理)

async/await在使用過程中有什么規(guī)定

每個(gè)async方法都返回一個(gè)promise, await只能出現(xiàn)在async函數(shù)中

async/await在什么場(chǎng)景使用

單一的promise鏈并不能發(fā)現(xiàn)async/await的有事,但是如果需要處理由多個(gè)promise組成的then鏈的時(shí)候,優(yōu)勢(shì)就能體現(xiàn)出來了(Promise通過then鏈來解決多層回調(diào)的問題,現(xiàn)在又用async/awai來進(jìn)一步優(yōu)化它)

2. 作用域、閉包

閉包

  • 閉包是指有權(quán)訪問另外一個(gè)函數(shù)作用域中的變量的函數(shù)(紅寶書)
  • 閉包是指那些能夠訪問自由變量的函數(shù)。(MDN)其中自由變量, 指在函數(shù)中使用的,但既不是函數(shù)參數(shù)arguments也不是函數(shù)的局部變量的變量,其實(shí)就是另外一個(gè)函數(shù)作用域中的變量。)

作用域

說起閉包,就必須要說說作用域,ES5種只存在兩種作用域:

  • 函數(shù)作用域。
  • 全局作用域 當(dāng)訪問一個(gè)變量時(shí),解釋器會(huì)首先在當(dāng)前作用域查找標(biāo)示符,如果沒有找到, 就去父作用域找, 直到找到該變量的標(biāo)示符或者不在父作用域中
  • 這就是作用域鏈,每一個(gè)子函數(shù)都會(huì)拷貝上級(jí)的作用域, 形成一個(gè)作用域的鏈條。
let a = 1;
function f1() {
    var a = 2
  function f2() {
       var a = 3;
       console.log(a); //3
   }
}

在這段代碼中,

  • f1的作用域指向有全局作用域(window) 和它本身
  • 而f2的作用域指向全局作用域(window)、 f1和它本身
  • 而且作用域是從最底層向上找, 直到找到全局作用域window為止
  • 如果全局還沒有的話就會(huì)報(bào)錯(cuò)。閉包產(chǎn)生的本質(zhì)就是
  • 當(dāng)前環(huán)境中存在指向父級(jí)作用域的引用
function f2() {
    var a = 2
    function f3() {
        console.log(a); //2
    }
    return f3;
}
var x = f2();
x();

這里x會(huì)拿到父級(jí)作用域中的變量, 輸出2。

因?yàn)樵诋?dāng)前環(huán)境中,含有對(duì)f3的引用, f3恰恰引用了window、 f3和f3的作用域。

因此f3可以訪問到f2的作用域的變量。那是不是只有返回函數(shù)才算是產(chǎn)生了閉包呢?回到閉包的本質(zhì),只需要讓父級(jí)作用域的引用存在即可。

var f4;
function f5() {
    var a = 2
    f4 = function () {
        console.log(a);
    }
}
f5();
f4();

讓f5執(zhí)行,給f4賦值后,等于說現(xiàn)在f4擁有了window、f5和f4本身這幾個(gè)作用域的訪問權(quán),還是自底向上查找,最近是在f5中找到了a,因此輸出2。在這里是外面的變量f4存在著父級(jí)作用域的引用,

因此產(chǎn)生了閉包,形式變了,本質(zhì)沒有改變。

場(chǎng)景

  • 返回一個(gè)函數(shù)
  • 作為函數(shù)參數(shù)傳遞
  • 在定時(shí)器、 事件監(jiān)聽、 Ajax請(qǐng)求、 跨窗口通信、 Web Workers或者任何異步中,只要使用了回調(diào)函數(shù), 實(shí)際上就是在使用閉包。

IIFE(立即執(zhí)行函數(shù)表達(dá)式) 創(chuàng)建閉包, 保存了全局作用域window和當(dāng)前函數(shù)的作用域。

	var b = 1;
	function foo() {
	    var b = 2;
	
	    function baz() {
	        console.log(b);
	    }
	    bar(baz);
	}
	function bar(fn) {
	    // 這就是閉包
	    fn();
	}
	// 輸出2,而不是1
	foo();
	// 以下的閉包保存的僅僅是window和當(dāng)前作用域。
	// 定時(shí)器
	setTimeout(function timeHandler() {
	   console.log('111');
	}, 100)
	
	// 事件監(jiān)聽
	// document.body.click(function () {
	//     console.log('DOM Listener');
	// })
	// 立即執(zhí)行函數(shù)
	var c = 2;
	(function IIFE() {
	    // 輸出2
	    console.log(c);
	})();

經(jīng)典的一道題

for (var i = 1; i <= 5; i++) {
    setTimeout(function timer() {
        console.log(i)
    }, 0)
}  // 6 6 6 6 6 6
// 為什么會(huì)全部輸出6? 如何改進(jìn), 讓它輸出1, 2, 3, 4, 5?

解析:

  • 因?yàn)閟etTimeout為宏任務(wù), 由于JS中單線程eventLoop機(jī)制, 在主線程同步任務(wù)執(zhí)行完后才去執(zhí)行宏任務(wù)。
  • 因此循環(huán)結(jié)束后setTimeout中的回調(diào)才依次執(zhí)行, 但輸出i的時(shí)候當(dāng)前作用域沒有。

往上一級(jí)再找,發(fā)現(xiàn)了i,此時(shí)循環(huán)已經(jīng)結(jié)束,i變成了6,因此會(huì)全部輸出6。

利用IIFE(立即執(zhí)行函數(shù)表達(dá)式)當(dāng)每次for循環(huán)時(shí),把此時(shí)的i變量傳遞到定時(shí)器中

	for (var i = 0; i < 5; i++) {
	    (function (j) {
	        setTimeout(() => {
	            console.log(j)
	        }, 1000);
	    })(i)
	}

給定時(shí)器傳入第三個(gè)參數(shù), 作為timer函數(shù)的第一個(gè)函數(shù)參數(shù)

for (var i = 0; i < 5; i++) {
	    setTimeout(function (j) {
	        console.log(j)
	    }, 1000, i);
	}

使用ES6中的let

  • let使JS發(fā)生革命性的變化, 讓JS有函數(shù)作用域變?yōu)榱藟K級(jí)作用域
  • 用let后作用域鏈不復(fù)存在。 代碼的作用域以塊級(jí)為單位,
for (let i = 1; i <= 5; i++) {
    setTimeout(function timer() {
        console.log(i)
    }, 2000)
}

3. 原型、原型鏈

原型(prototype)

JS中所有函數(shù)都會(huì)有prototype屬性,只有函數(shù)才有

其所有的屬性和方法都能被構(gòu)造函數(shù)的實(shí)例對(duì)象共享訪問

代碼如下:

function Person(name){
		this.name = name
	}
	Person.prototype.sayHello(){
		console.log('sayHello')
	}
	let p1 = new Person();
	let p2 = new Person();
	console.log(p1.sayHello) //sayHello
	console.log(p2.sayHello) //sayHello

構(gòu)造函數(shù)(constructor)

JS中constructor存在每個(gè)函數(shù)的prototype屬性中,其保存了指向該函數(shù)的引用

Person.prototype.constructor ==Person   //true

原型鏈(_ _ proto _ _)

JS中對(duì)象都會(huì)有個(gè)內(nèi)置屬性,即__proto__,(隱式原型鏈的屬性),一般情況下執(zhí)行創(chuàng)建它的構(gòu)造函數(shù)的prototype的屬性,另外函數(shù)比較特殊,也會(huì)有該屬性

p1.__proto__ == Person.prototype

JS 引擎查找摸個(gè)屬性時(shí),先查找對(duì)象本身是否存在該屬性,如果不存在就會(huì)在原型鏈上一層一層進(jìn)行查找

有幾個(gè)面試經(jīng)常會(huì)問的幾個(gè)問題

如何精確地判斷短數(shù)組的類型

[] instanceof Array   //[].__proto__ == Array.prototype
Object.prototype.toString.call([])  //[Object Array]
Array.isArray([]) //true
[].constructor ==Array

下面代碼輸出什么

Object instanceof Function //true
Function instanceof Object // true

實(shí)現(xiàn)一個(gè)原型鏈繼承

	function Person(name){
		this.name = name
	}
	Person.prototype.sayHello(){
		console.log('sayHello')
	}
	function Boy(){};
	Boy.prototype = new Person();
	let b1 = new Boy();
	b1.sayHello() //sayHello

原型、原型鏈、構(gòu)造函數(shù)、實(shí)例的關(guān)系

1.instanceof檢測(cè)構(gòu)造函數(shù)與實(shí)例的關(guān)系:

	function Person () {.........}
	person = new Person ()
	res = person instanceof Person
	res  // true

2.實(shí)例繼承原型上的定義的屬性:

	function Person () {........}
	Person.prototype.type = 'object n'
	person = new Person ()
	res = person.type
	res  // object n

3.實(shí)例訪問 ===> 原型

實(shí)例通過__proto__訪問到原型 person.proto=== Person.prototype

4.原型訪問 ===> 構(gòu)造函數(shù)

原型通過constructor屬性訪問構(gòu)造函數(shù) Person.prototype.constructor === Person

5.實(shí)例訪問===>構(gòu)造函數(shù)

person.proto.constructor === Person

原型鏈

在讀取一個(gè)實(shí)例的屬性的過程中,如果屬性在該實(shí)例中沒有找到,那么就會(huì)循著 proto 指定的原型上去尋找,如果還找不到,則尋找原型的原型:

實(shí)例上尋找

function Person() {}
    Person.prototype.type = "object name Person";
    person = new Person();
    person.type = "我是實(shí)例的自有屬性";
    res = Reflect.ownKeys(person); //嘗試獲取到自有屬性
    console.log(res);
    res = person.type;
    console.log(res); //我是實(shí)例的自有屬性(通過原型鏈向上搜索優(yōu)先搜索實(shí)例里的)

原型上尋找

function Person() {}
    Person.prototype.type = "object name Person";
    person = new Person();
    res = Reflect.ownKeys(person); //嘗試獲取到自有屬性
    console.log(res);
    res = person.type;
    console.log(res); //object name Person

原型的原型上尋找

function Person() {}
    Person.prototype.type = "object name Person";
    function Child() {}
    Child.prototype = new Person();
    p = new Child();
    res = [p instanceof Object, p instanceof Person, p instanceof Child];
    console.log(res); //[true, true, true] p同時(shí)屬于Object,Person, Child
    res = p.type; //層層搜索
    console.log(res); //object name Person (原型鏈上搜索)
    console.dir(Person);
    console.dir(Child);

原型鏈上搜索

原型同樣也可以通過 proto 訪問到原型的原型,比方說這里有個(gè)構(gòu)造函數(shù) Child 然后“繼承”前者的有一個(gè)構(gòu)造函數(shù) Person,然后 new Child 得到實(shí)例 p;

當(dāng)訪問 p 中的一個(gè)非自有屬性的時(shí)候,就會(huì)通過 proto 作為橋梁連接起來的一系列原型、原型的原型、原型的原型的原型直到 Object 構(gòu)造函數(shù)為止;

原型鏈搜索搜到 null 為止,搜不到那訪問的這個(gè)屬性就停止:

function Person() {}
  Person.prototype.type = "object name Person";
  function Child() {}
  Child.prototype = new Person();
  p = new Child();
  res = p.__proto__;
  console.log(res);         //Person {}
  res = p.__proto__.__proto__;
  console.log(res);         //Person {type:'object name Person'}
  res = p.__proto__.__proto__.__proto__;
  console.log(res);         //{.....}
  res = p.__proto__.__proto__.__proto__.__proto__;
  console.log(res);         //null

繼承

  • JS 中一切皆對(duì)象(所有的數(shù)據(jù)類型都可以用對(duì)象來表示),必須有一種機(jī)制,把所有的對(duì)象聯(lián)系起來,實(shí)現(xiàn)類似的“繼承”機(jī)制。
  • 不同于大部分面向?qū)ο笳Z言,ES6 之前并沒有引入類(class)的概念,JS 并非通過類而是通過構(gòu)造函數(shù)來創(chuàng)建實(shí)例,javascript中的繼承是通過原型鏈來體現(xiàn)的。
  • 其基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用繼承的屬性和方法。

什么是繼承

  • js中,繼承是一種允許我們?cè)谝延蓄惖幕A(chǔ)上創(chuàng)建新類的機(jī)制;它可以使用現(xiàn)有類的所有功能,并在無需重新編寫
  • 原來的類的情況下對(duì)這些功能進(jìn)行擴(kuò)展。

為什么要有繼承

提高代碼的重用性、較少代碼的冗余

目前我總結(jié)的一共有6種繼承方式

  • 原型鏈繼承
  • 借用構(gòu)造函數(shù)繼承
  • 組合式繼承(原型鏈+構(gòu)造函數(shù))
  • 原型式繼承
  • 寄生式繼承
  • 寄生組合式繼承
function Person(name){
	this.name = name;
	this.sum=function(){
		alert('this.name',this.name)
	}
}
Person.prototype.age = 100

原型鏈繼承

實(shí)現(xiàn)方式: 利用原型鏈的特點(diǎn)繼承,讓實(shí)例的原型等于父類的實(shí)例

優(yōu)點(diǎn): 實(shí)例可以繼承父類的構(gòu)造個(gè)函數(shù),實(shí)例的構(gòu)造函數(shù),父類的原型

缺點(diǎn): 不能向父類傳遞參數(shù),由于實(shí)例的原型等于父類的實(shí)例,那么改變父類的屬性,實(shí)例的屬性也會(huì)跟著改變

function child(){
	this.name="xiaoming"
}
child.prototype = new Person()
let child1 = new Child()
child1.name //xiaoming
child1.age //100
child1 instanceof Person //true

借用構(gòu)造函數(shù)繼承

實(shí)現(xiàn)方式: 使用call/apply將父類的構(gòu)造函數(shù)引入子類函數(shù)

優(yōu)點(diǎn): 可以禰補(bǔ)原型鏈繼承的缺點(diǎn),可以向父類傳遞參數(shù),只繼承父類構(gòu)造函數(shù)的屬性

缺點(diǎn): 不能復(fù)用,每次使用需要重新調(diào)用,每個(gè)實(shí)例都是父類構(gòu)造函數(shù)的副本,比較臃腫

	function child(){
		Person.call(this,'xiaoming')
	}
	let child1 = new child()
	child1.name //xiaoming
	child1.age //100
	child1 instanceof Person //false

組合式繼承

實(shí)現(xiàn)方式: 復(fù)用+可傳遞參數(shù)

優(yōu)點(diǎn): 基于原型鏈的優(yōu)點(diǎn)和借用構(gòu)造函數(shù)的優(yōu)點(diǎn)

缺點(diǎn): 調(diào)用兩遍父類函數(shù)

	function child(){
		Person.call(this,'xiaoming')
	}
	child.prototype = new Person 
	let child1 = new child()
	child1.name //xiaoming
	child1.age //100
	child1 instanceof Person //true
	child instanceof Person //false

原型式繼承

實(shí)現(xiàn)方式: 函數(shù)包裝對(duì)象,返回對(duì)象的引用,這個(gè)函數(shù)就變成可以隨時(shí)添加實(shí)例或者對(duì)象,Object.create()就是這個(gè)原理

優(yōu)點(diǎn): 復(fù)用一個(gè)對(duì)象用函數(shù)包裝

缺點(diǎn): 所有實(shí)例都繼承在原型上面 無法復(fù)用

	function child(obj){
		 function F(){}
		 F.prototype = obj
		 return new F()
	}
	let child1 = new Person()
	let child2 = child(child1)
	child2.age //100

寄生式繼承

實(shí)現(xiàn)方式: 在原型式繼承外面包了一個(gè)殼子

優(yōu)點(diǎn): 創(chuàng)建一個(gè)新對(duì)象

缺點(diǎn): 沒有用到實(shí)例 無法復(fù)用

	function child(obj){
		 function F(){}
		 F.prototype = obj
		 return new F()
	}
	let child1 = new Person()
	function subObject(){
		let sub =child(child1)
		sub.name='xiaoming'
		return sub
	}
	let child2 = subObject(child1)
	typeof subObject //function
	typeof child2 //object
	child2.age //100

寄生組合式繼承

實(shí)現(xiàn)方式: 在函數(shù)內(nèi)返回對(duì)象的調(diào)用

優(yōu)點(diǎn): 函數(shù)的實(shí)例等于另外的一個(gè)實(shí)例,使用call/apply引入另一個(gè)構(gòu)造函數(shù),可傳遞參數(shù),修復(fù)了組合繼承的問題

缺點(diǎn): 無法復(fù)用

	function child(obj){
			 function F(){}
			 F.prototype = obj
			 return new F()
		}
		let child1 = child(Person.prototype)
		function Sub(){
			Person.call(this)
		}
		Sub.prototype = child
		child.constructor = Sub
		let sub1 = new Sub()
		sub1.age //100

到此這篇關(guān)于JavaScript三大重點(diǎn)同步異步與作用域和閉包及原型和原型鏈詳解的文章就介紹到這了,更多相關(guān)JavaScript 同步異步內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論