基本類型和引用類型#
ECMAScript包含兩種不同的數(shù)據(jù)類型:基本類型值和引用類型值;
基本類型值指的是保存在棧內(nèi)存中的簡單數(shù)據(jù)段,null,undefined,Boolean,Number和String都是基本數(shù)據(jù)類型,它們都是按值訪問的,因?yàn)榭梢圆僮鞅4嬖谧兞恐械膶?shí)際值;
引用類型值(對象径密、數(shù)組舆逃、函數(shù)、正則):指的是那些保存在堆內(nèi)存中的對象狈涮,變量中保存的實(shí)際上只是一個指針,這個指針執(zhí)行內(nèi)存中的另一個位置隆箩,由該位置保存對象
值得注意的是:string雖然屬于基本類型,但是由于自身只讀的原因,是無法修改的,這導(dǎo)致給相同的字符串賦不同的變量,不同的變量指向了同一個字符串的位置,在這點(diǎn)上有點(diǎn)類似引用類型.
<h2>JS的內(nèi)存空間</h2>
這里兩篇文章有利于理解js的內(nèi)存空間問題
博客園文章
內(nèi)存空間圖解
<h2>深淺拷貝</h2>
在Javascript 中辖所,將一個對象賦值給一個變量其實(shí)只是將這個對象的引用拷貝了一份;
<h4>淺拷貝:</h4>
主要針對對象等引用類型
所謂淺拷貝,個人理解就是簡單的拷貝了引用關(guān)系,指針指向依然是指向堆內(nèi)存中的同一個存儲地址,這樣當(dāng)我們改變一個對象的屬性的時候,另一個對象的屬性也跟著改變了(因?yàn)閷?shí)質(zhì)只是對象的名稱改變了,指向沒有改變,或者說實(shí)質(zhì)上的鍵值對并沒有改變)
舉例說明:
var a = {name :"frank"}; b = a;//將a的值(存放指向堆內(nèi)存中內(nèi)容的地址指針)拷貝給b b.name = "jack"; a.name === "jack";//這種情況就是淺拷貝,當(dāng)改變b的屬性時,a的屬性也會跟著發(fā)生改變
<h4>深拷貝</h4>
所謂深拷貝,個人理解就是將被拷貝對象的所有內(nèi)容完全復(fù)制,并在堆內(nèi)存中開辟了一個新的內(nèi)存空間來存放,這個時候拷貝對象和被拷貝對象是完全獨(dú)立的兩個變量,當(dāng)拷貝對象或者被拷貝對象的內(nèi)容發(fā)生改變時,并不會互相影響;
沿用上面的例子:
var a = {name :"frank"}; b = a;//將a的值(存放指向堆內(nèi)存中內(nèi)容的地址指針)拷貝給b b.name = "jack"; a.name === "jack";//這種情況就是淺拷貝,當(dāng)改變b的屬性時,a的屬性也會跟著發(fā)生改變 b = deepClone(a);//利用深拷貝函數(shù)拷貝a,這個時候就a,b就是兩個獨(dú)立的變量,互不影響 b.name ="jack"; a,name = "frank";
<h1>復(fù)習(xí)部分</h1>
<h2>1.引用類型有哪些擅笔?非引用類型有哪些</h2>
- 非引用類型有基本數(shù)據(jù)類型,基本數(shù)據(jù)類型指的是保存在棧內(nèi)存中的簡單數(shù)據(jù)段;
- 引用類型值一般有對象,數(shù)組,函數(shù)及正則表達(dá)式,指的是保存在堆內(nèi)存中的對象,變量中保存的實(shí)際上是一個指針(地址),指向了引用類型的實(shí)際值;
<h2>2.如下代碼輸出什么险胰?為什么</h2>
//簡單分析
//1.利用對象字面量(文本代碼)方法構(gòu)造兩個對象obj1及obj2
//2.obj1 == obj2, obj1與obj2存放的地址應(yīng)該不一致,所以是不等的
//3.console.log(obj1 == obj2)輸出應(yīng)該為false;
/*4.將obj2中的地址賦給了obj1,此時兩者存放的指針指向的儲值地址應(yīng)該是一致的*/
//5.console.log(obj1 = obj2),輸出的應(yīng)該是obj2對象的鍵值對;
//6.console.log(obj1 == obj2),地址一致,輸出應(yīng)該是true
與分析是一致的;
<h2>3.如下代碼輸出什么? 為什么</h2>
1.定義4個變量,分別為整型,對象,以及數(shù)組;
2.又定義4個變量,其中aa,bb數(shù)值為單純復(fù)制1,2
cc與c的存儲指針指向一致,dd與d存儲的指針指向一致;- a,b存儲的值分別變?yōu)?1,22;
c.name改變,相應(yīng)的cc.name也會改變,因?yàn)榇尜A的指針指向是一致的
d[2]['age'] = 3 相當(dāng)于改變了下標(biāo)為2的數(shù)組對象的age屬性值為3,即c.age=3同時cc.age=3;
- a,b存儲的值分別變?yōu)?1,22;
4.console.log(aa)輸出為1
5.console.log(bb)輸出為2
6.console.log(cc)輸出為Object{
name:'hello',
age:3
};7.console.log(dd)輸出為array[
0:1
1:2;
2:object{
name:"hello",
age: 3
}
];
<h2>4.如下代碼輸出什么? 為什么</h2>
- 聲明并定義變量a,b,分別為整型及對象;
- 聲明兩個函數(shù)f1及f2;
- 調(diào)用f1(),傳入?yún)?shù)a,a=1;
- function f1(n){
var n = a;//相當(dāng)于單純復(fù)制了值;
++n;//n變?yōu)榱?1,但是對a并沒有影響;
} - 調(diào)用f2(),傳入?yún)?shù)c,c存貯指向?qū)嶋H值地址的指針;
- function f2(c){
var obj = c;//變量obj存儲指針一致
++obj.age//相當(dāng)于c.age+1
} - console.log(a),輸出1;
- console.log(c),輸出:
object{
name:"饑人谷",
age:3
};
<h2>5.過濾如下數(shù)組汹押,只保留正數(shù),直接在原數(shù)組上操作</h2>
var arr = [3,1,0,-1,-3,2,-5];
function filter(arr){
for(var i = 0; i < arr.length;i++ ){
if(arr[i]<=0){
arr.splice(i,1);
filter(arr);
}
}
}
filter(arr);
console.log(arr);//[3,1,2]
<h2>6.過濾如下數(shù)組起便,只保留正數(shù)棚贾,原數(shù)組不變,生成新數(shù)組</h2>
var arr =[3,1,0,-1,-3,2,-5]
var newArr = [];
function filter(arr){
for(var key in arr ){
if(arr[key] > 0){
newArr.push(arr[key]);
}
}
return newArr;
}
var arr2 = filter(arr);
console.log(arr2)//[3,1,2]
console.log(arr)//[3,1,0,-1,-2,2,-5]
<h2>7.寫一個深拷貝函數(shù)榆综,用兩種方式實(shí)現(xiàn)</h2>
第一種
var person={
name:"wuyanwen",
age: 24
};
function deepCopy(oldObj) {
var newObj = {};
for(var key in oldObj) {
if(typeof oldObj[key] === 'object') {
newObj[key] = deepCopy(oldObj[key]);
}else{
newObj[key] = oldObj[key];
}
}
return newObj;
}
var newPerson = deepCopy(person)
newPerson.name = "wuyanwen24";
console.log(person.name);
console.log(newPerson.name);第二種
var person={
name:"wuyanwen",
age: 24
};
function copy(obj){
var newobj = JSON.parse(JSON.stringify(obj));
return newobj;
}
var newPerson = copy(person);
newPerson.name = "wuyanwen24";
console.log(person.name);
console.log(newPerson.name);