摘要:返回如下仔細(xì)分析下面的圖,將會(huì)加深你的理解和我們有一個(gè)類(lèi)對(duì)象有一個(gè)屬性,其指向構(gòu)造器的原型是一個(gè)類(lèi)構(gòu)造器是之后產(chǎn)生的。
擼js基礎(chǔ)之對(duì)象 圖例 先談?wù)?ECMAScript 中的數(shù)據(jù)類(lèi)型
ES6 之前 ECMAScript 中有 5 種簡(jiǎn)單數(shù)據(jù)類(lèi)型(也稱(chēng)為【基本數(shù)據(jù)類(lèi)型】):Undefined、Null、Boolean、Number和 String。
還有一種復(fù)雜的【引用數(shù)據(jù)類(lèi)型】Object。
ES6引入了一種新的原始數(shù)據(jù)類(lèi)型 Symbol,表示獨(dú)一無(wú)二的值。它是 JavaScript 語(yǔ)言的第七種數(shù)據(jù)類(lèi)型。它也是基本數(shù)據(jù)類(lèi)型。
特點(diǎn)
基本數(shù)據(jù)類(lèi)型的值是按值訪問(wèn)的 基本類(lèi)型的值是不可變的 基本類(lèi)型的比較是它們的值的比較 基本類(lèi)型的變量是存放在棧內(nèi)存(Stack)里的 引用類(lèi)型的值是按引用訪問(wèn)的 引用類(lèi)型的值是可變的 引用類(lèi)型的比較是引用的比較 引用類(lèi)型的值是保存在堆內(nèi)存(Heap)中的對(duì)象(Object) 與其他編程語(yǔ)言不同,JavaScript 不能直接操作對(duì)象的內(nèi)存空間(堆內(nèi)存)
圖解:
檢測(cè)變量類(lèi)型typeof
適合判斷基本數(shù)據(jù)類(lèi)型和function的判斷
typeof "sss" ===> "string" typeof 123 ===> "Number" typeof [1,2,3] ===> "object" typeof new Date() ===> "object" typeof function(){alert("111");} ===> "function" typeof undefined ===> "undefined" typeof NaN ===> "number" typeof null ===> "object"
instanceof
判斷已知的對(duì)象類(lèi)型或者是自定義的對(duì)象
目標(biāo)對(duì)象 + instanceof + 函數(shù)構(gòu)造器[可以理解為是某個(gè)對(duì)象是否是某個(gè)構(gòu)造器的實(shí)例]
原理: 判斷左邊的對(duì)象的原型鏈上是否有右側(cè)的構(gòu)造函數(shù)的prototype屬性
[1,3] instanceof Array === true new Array("1, 3,4") instanceof Array === true new Object() instanceof Object === true new String("string") instanceof String === true function(){this.name="22";} instanceof Function === true // 定義一個(gè)構(gòu)造函數(shù) function Person(){ } // 定義一個(gè)構(gòu)造函數(shù) function Student(){ } // 每一個(gè)構(gòu)造函數(shù)都有一個(gè)prototype對(duì)象屬性, 這個(gè)對(duì)象屬性將會(huì)作為通過(guò)new Person()創(chuàng)建的對(duì)象的一個(gè)原型。 // 也就是當(dāng)我們?cè)趎ew 一個(gè)對(duì)象的時(shí)候,這個(gè)對(duì)象的原型就指向了這個(gè)構(gòu)造函數(shù)的prototype。 Student.prototype = new Person(); // student繼承至person var bson = new Student(); bson instanceof Student // false bson instanceof Person // true
Object.prototype.toString.apply()
判斷基本數(shù)據(jù)類(lèi)型和內(nèi)置對(duì)象
Object.prototype.toString.apply([]) === "[object Array]" Object.prototype.toString.apply(function(){}) === "[object Function]" Object.prototype.toString.apply(new Function); // "[object Function]" Object.prototype.toString.apply(new Object); // "[object Object]" Object.prototype.toString.apply(new Date); // "[object Date]" Object.prototype.toString.apply(new Array); // "[object Array]" Object.prototype.toString.apply(new RegExp); // "[object RegExp]" Object.prototype.toString.apply(new ArrayBuffer); // "[object ArrayBuffer]" Object.prototype.toString.apply(Math); // "[object Math]" Object.prototype.toString.apply(JSON); // "[object JSON]" var promise = new Promise(function(resolve, reject) { resolve(); }); Object.prototype.toString.apply(promise); // "[object Promise]" Object.prototype.toString.apply(124) // "[object Number]" Object.prototype.toString.apply("222") // "[object String]" Object.prototype.toString.apply(true) // "[object Boolean]" Object.prototype.toString.apply(null) // "[object Null]" Object.prototype.toString.apply(null) === "[object Null]" // 在IE6/7/8下存在有兼容性問(wèn)題創(chuàng)建對(duì)象
使用 Object 構(gòu)造函數(shù)創(chuàng)建
// 對(duì)象實(shí)例的創(chuàng)建 var obj = new Object() obj.key = "value" //使用構(gòu)造函數(shù)創(chuàng)建一個(gè)空對(duì)象,并賦值
使用對(duì)象字面量表示法創(chuàng)建
//使用字面量創(chuàng)建一個(gè)對(duì)象 var obj = { key1: "value1", key2: "value2" }
ES6中還有更簡(jiǎn)潔的
var age = 20 var sex = "sexy" var a = { name: "jack", // 簡(jiǎn)潔表示法,等同于 age: age age, // 簡(jiǎn)潔表示法,等同于 sayName: function() {} sayName(){}, // 屬性名表達(dá)式,等同于 lover: "rose" ["lo" + "ver"]: "rose", // 屬性名表達(dá)式,等同于 sexy: "male" [sex]: "male" }工廠模式[創(chuàng)建多個(gè)相似的對(duì)象]
var createPerson (name, age){ var o = {}; o.name = name; o.age = age; o.sayName = function(){ console.log(this); } return o; } var a = createPerson ("zjj", 20); var b = createPerson ("zmf", 30);
工廠模式雖然解決多創(chuàng)建多個(gè)相似對(duì)象的問(wèn)題,但卻沒(méi)有解決對(duì)象識(shí)別的問(wèn)題(即怎樣知道一個(gè)對(duì)象的類(lèi)型)。
模仿“類(lèi)”的設(shè)計(jì)構(gòu)造函數(shù)模式
function Person (name, age) { this.name = name; thia.age = age; this.sayName = function() { alert(this.age) } } Person.prototype.count = 2; var a = new Person("a", 20) var b = new Person("b", 22) a instanceof Person // true
構(gòu)造函數(shù)與其他函數(shù)唯一的區(qū)別就在于調(diào)用他們的方式不同。任何函數(shù)只要通過(guò)new 操作符來(lái)調(diào)用,那它就可以作為構(gòu)造函數(shù)。
使用new操作符調(diào)用函數(shù)
function CO(){ this.p = “I’m in constructed object”; this.alertP = function(){ alert(this.p); } } var o2 = new CO(); var obj = {}; // 第一步創(chuàng)建一個(gè)空對(duì)象 obj.__proto__ = CO.prototype; // 該對(duì)象的原型鏈指向構(gòu)造函數(shù)的 prototype 所指向的對(duì)象。 CO.call(obj); // 第三步,將構(gòu)造函數(shù)的作用域賦值給新的對(duì)象 return obj; // 返回新的對(duì)象
自定義一個(gè)new()
function Person(name, age) { this.name = name; this.age = age; } function New(f) { return function() { var o = {"__proto__": f.prototype} f.apply(o, arguments); return o; } }
上面這種構(gòu)造函數(shù)解決了對(duì)象類(lèi)型識(shí)別的問(wèn)題,但是每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍,在上面的例子中,a 和 b 都有個(gè)名為sayName()的方法,這兩個(gè)方法雖然名字、內(nèi)容、功能相同,但卻分別在 a 和 b 中都重新創(chuàng)建了一次,這是沒(méi)有必要的。
更好的方法應(yīng)該是將公用的方法放到他們的原型上,也就是接下來(lái)要說(shuō)的原型模式。
原型模式
所有函數(shù)都有一個(gè)不可枚舉的 prototype(原型)屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象。
Person.prototype
返回如下:
仔細(xì)分析下面的圖,將會(huì)加深你的理解
prototype 和 proto
我們有一個(gè)person類(lèi)
function Person (name, age) { this.name = name; thia.age = age; this.sayName = function() { alert(this.age) } } Person.prototype.count = 2; var p = new Person("zjj", 10);
對(duì)象p有一個(gè)__proto__屬性,其指向構(gòu)造器的原型
p.__proto__ == Person.prototype
foo 是一個(gè)類(lèi)(構(gòu)造器) fooObj是new foo() 之后產(chǎn)生的。 fooObj的 __proto__ 指向構(gòu)造器原型(foo.prototype) foo 通過(guò)prototype 指向 構(gòu)造器原型(foo.prototype) 構(gòu)造器原型(foo.prototype)的構(gòu)造器屬性constructor 指向 foo
Person.__proto__ === Function.prototype
__proto__究竟指向誰(shuí)
原型鏈由于Person.prototype.__proto__ === Object.prototype,這就
相信看了上面兩幅圖,大家一定對(duì)原型鏈有了更深的理解和認(rèn)識(shí)了吧??!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96762.html
摘要:本計(jì)劃一共期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)劃,點(diǎn)擊查看前端進(jìn)階的破冰之旅本期推薦文章深入之執(zhí)行上下文棧和深入之變量對(duì)象,由于微信不能訪問(wèn)外鏈,點(diǎn)擊閱讀原文就可以啦。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第二天。 本計(jì)劃一共28期,每期...
摘要:深入系列第九篇,除了按值傳遞引用傳遞,還有第三種傳遞方式按共享傳遞定義在高級(jí)程序設(shè)計(jì)第三版,講到傳遞參數(shù)中所有函數(shù)的參數(shù)都是按值傳遞的。 JavaScript深入系列第九篇,除了按值傳遞、引用傳遞,還有第三種傳遞方式 —— 按共享傳遞 定義 在《JavaScript高級(jí)程序設(shè)計(jì)》第三版 4.1.3,講到傳遞參數(shù): ECMAScript中所有函數(shù)的參數(shù)都是按值傳遞的。 什么是按值傳遞呢?...
摘要:前言本章我們要講解的是五大原則語(yǔ)言實(shí)現(xiàn)的第篇,接口隔離原則。接口隔離原則和單一職責(zé)有點(diǎn)類(lèi)似,都是用于聚集功能職責(zé)的,實(shí)際上可以被理解才具有單一職責(zé)的程序轉(zhuǎn)化到一個(gè)具有公共接口的對(duì)象。與我們下面討論的一些小節(jié)是里關(guān)于違反接口隔離原則的影響。 前言 本章我們要講解的是S.O.L.I.D五大原則JavaScript語(yǔ)言實(shí)現(xiàn)的第4篇,接口隔離原則ISP(The Interface Segreg...
摘要:閉包面試題解由于作用域鏈機(jī)制的影響,閉包只能取得內(nèi)部函數(shù)的最后一個(gè)值,這引起的一個(gè)副作用就是如果內(nèi)部函數(shù)在一個(gè)循環(huán)中,那么變量的值始終為最后一個(gè)值。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第8天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了...
摘要:使用上一篇文章的例子來(lái)說(shuō)明下自由變量進(jìn)階期深入淺出圖解作用域鏈和閉包訪問(wèn)外部的今天是今天是其中既不是參數(shù),也不是局部變量,所以是自由變量。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第7天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)...
摘要:進(jìn)階期理解中的執(zhí)行上下文和執(zhí)行棧進(jìn)階期深入之執(zhí)行上下文棧和變量對(duì)象但是今天補(bǔ)充一個(gè)知識(shí)點(diǎn)某些情況下,調(diào)用堆棧中函數(shù)調(diào)用的數(shù)量超出了調(diào)用堆棧的實(shí)際大小,瀏覽器會(huì)拋出一個(gè)錯(cuò)誤終止運(yùn)行。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第3天。 本計(jì)劃一共28期,每期重點(diǎn)攻...
閱讀 2649·2021-09-28 09:36
閱讀 2273·2021-09-07 09:58
閱讀 1536·2019-08-26 13:53
閱讀 1313·2019-08-23 17:53
閱讀 3059·2019-08-23 15:34
閱讀 1882·2019-08-23 15:34
閱讀 2907·2019-08-23 12:04
閱讀 3754·2019-08-23 10:56