在面向?qū)ο蠹昂瘮?shù)編程語言中阅嘶,不可變對象是一種對象。在被創(chuàng)造之后载迄,它的狀態(tài)就不可以被改變讯柔。狀態(tài)可以被改變的對象,則被稱為可變對象护昧。
這里狀態(tài)可以簡單理解為對象的值魂迄。
在javascript中,原始值(undefined, null, 布爾值惋耙, 數(shù)字和字符串)這些都是不可變原始值捣炬。
理解:不可變說的是一旦這些基本類型值創(chuàng)建后會一直保存其內(nèi)存地址熊昌,直到被瀏覽器的垃圾回收機制回收。而我們一直用的創(chuàng)建一個字符串變量湿酸,只是將這個變量指向了該字符串的內(nèi)存地址婿屹,當(dāng)改變該變量的值,也就是改變了該變量指向的字符串內(nèi)存地址稿械,而原來的字符串還在內(nèi)存中存在选泻。
js對象的屬性值發(fā)生改變,會創(chuàng)建一個新的屬性值,然后改變的是該屬性指向的內(nèi)存地址桐汤。對象本身的內(nèi)存地址是沒有改變的系宫。這樣對象的內(nèi)存地址沒有變化。
原始值
:任何方法都無法更改一個原始值窝撵。
示例:
let s = 'hello'; // 這里申請內(nèi)存,并保存數(shù)據(jù)hello襟铭,并把內(nèi)存地址賦給
s.toUpperCase(); // 生成一個新的數(shù)據(jù)HELLO碌奉,并申請內(nèi)存保存之
s = s.toUpperCase(); // 把新的內(nèi)存地址賦給s,此時s的值就是HELLO了寒砖。原來的'hello'會被回收赐劣。
一、js數(shù)據(jù)
1.typeof
-
typeof
返回一個字符串哩都,指示未經(jīng)計算操作數(shù)的類型魁兼。 -
typeof
能區(qū)分值類型的詳細(xì)類型,但對于引用類型就不行了漠嵌。 -
typeof null
返回object是歷史遺留問題咐汞,自從js出現(xiàn)就是這樣的。 -
typeof
通常只返回6種數(shù)據(jù)類型:number
,string
,boolean
,undefined
,object
,function
,symbol
js的typeof數(shù)據(jù)類型.png
2.instanceof
instanceof 運算符用來測試一個對象在其原型鏈中是否存在一個構(gòu)造函數(shù)
的 prototype 屬性儒鹿。
語法:
// obj是使用構(gòu)造函數(shù)構(gòu)造的變量化撕,Object是構(gòu)造函數(shù)的名稱
obj instanceof Object
3.字面量創(chuàng)建變量和new 構(gòu)造函數(shù)創(chuàng)建變量
什么是字面量?
兩者區(qū)別:
- 字面量創(chuàng)建對象
let obj = { id: 1, };
let str = 'abc';
let num = 123;
上面創(chuàng)建變量時约炎,不會調(diào)用構(gòu)造函數(shù)植阴。是一個原始類型(基本類型)的值。
使用new
后圾浅,會將原始數(shù)據(jù)類型轉(zhuǎn)為對象墙贱。
- 構(gòu)造函數(shù)創(chuàng)建變量
let obj = new Object({ id:1 });
let str = new String('abc');
let num = new Number(123);
new
方式創(chuàng)建變量的本質(zhì)是方法調(diào)用,會遍歷__proto__
中的方法和屬性贱傀,找到該構(gòu)造函數(shù)的方法惨撇,然乎生產(chǎn)方法調(diào)用必須的堆棧信息,方法調(diào)用結(jié)束后府寒,還要釋放堆棧魁衙,性能不如字面量方式报腔。
問題:
- 字面量方式創(chuàng)建的變量,為什么有構(gòu)造函數(shù)函數(shù)創(chuàng)建的變量的方法和屬性剖淀?
可以參考這個問題
涉及到包裝類型
纯蛾。
發(fā)現(xiàn)一個有趣的:
image.png
4.原型
-
原型對象
:這個原型對象包含所有實例共享
的屬性和方法。其實最初指的是函數(shù)的prototype
纵隔。
image.png 當(dāng)使用構(gòu)造函數(shù)實例化時翻诉,實例化后的是對象,會將實例化對象的
__proto__
指向構(gòu)造函數(shù)的prototype
捌刮。任意一個
函數(shù)
(包括構(gòu)造函數(shù))都有一個prototype
屬性碰煌。函數(shù)也是對象。所有
對象
都有__proto__
屬性绅作。構(gòu)造函數(shù)實例化后的是一個對象芦圾。
自己理解示例:
let str = new String('abc')
一、str.__proto__
1. str.__proto__
是對象俄认,沒有prototype
个少。
2. str.__proto__
指向(或繼承)構(gòu)造函數(shù)String
的String.prototype
。
二眯杏、String.prototype
1. String.prototype
包含構(gòu)造函數(shù)String
自定義的屬性和方法夜焦。String.prototype
還包含構(gòu)造器constructor
和__proto__
。
1.1 String.protype.constructor
指向本身的函數(shù)String
1.2 String.prototype.__proto__
:因為String.protype.
是對象岂贩,下面無構(gòu)造函數(shù)了茫经,所以String.prototype.__proto__
指向的是對象的原型prototype
。對象指的不是Object
河闰,Object
是函數(shù)。
新建函數(shù)時姜性,函數(shù)的
prototype
下的__proto__
指向的是對象的原型prototype
部念。
新建的對象沒有prototype
屬性氨菇。
三、String.__proto__
1. String.__proto__
指向的是構(gòu)造函數(shù)String
的構(gòu)造函數(shù)Function
的prototype
乌询,即Function.prototype
妹田。
四、Function.prototype
-
Function.protype.constructor
指向本身的函數(shù)Function
image.png -
Function.prototype.__proto__
:因為Function.protype.
是對象鬼佣,下面無構(gòu)造函數(shù)了驶拱,所以Function.prototype.__proto__
指向的是對象的原型prototype
。
image.png
五晶衷、Function.__proto__
1. Function.__proto__
指向Function.prototype
蓝纲。即 Function.__proto__
和Function.prototype
相等。所以Function.__proto__
也指向的是對象的原型prototype
晌纫。
5.原型鏈
- 由于
__proto__
是任何對象都有的屬性税迷,所以最終會形成一條__proto__
連起來的鏈條,遞歸訪問__proto__
必須最終到頭缸匪,并且值是null翁狐。 - 當(dāng)js引擎查找對象的屬性時,先查找對象本身是否存在該屬性凌蔬,如果不存在露懒,會在原型鏈上找,但不會查找自身的
prototype
砂心。
image.png - 給原型
prototype
添加方法和屬性