1.引用類型有哪些?非引用類型有哪些
- ECMA Script中規定,javascript的基本數據類型分為兩類,即基本數據類型和引用類型,其中基本數據類型包括5樣,number、string 、boolean、以及undefined、null兩個特殊類型,其次引用類型包括狹義的Object、Array、Function、正則等.
- 其次,關于這兩種數據類型,他們的不同之處在于數據的保存的形式不同,對于基本類型的數據,其保存的方式是在內存中的??臻g,開辟一個固定大小的空間進行固定位置的保存,并且數據的訪問形式是后進先出,而引用類型的數據,其保存的形式是在內存的堆空間開辟一個動態的空間保存來保存數據的值(因為數據的大小不固定),當我們訪問這個變量的時候其實是根據出存在??臻g的指針尋址來查找到相應的堆內存空間,這也就是為什么,當我們給基本類型進行重復賦值的時候,基本數據的值不會改變,而引用類型會一起連帶改變,因為我們的改變不再是單獨去創建一個副本,而是查找了同一個指針引用并改變了其堆內存中的值 。
2. 如下代碼輸出什么?為什么
var obj1 = {a:1, b:2};
var obj2 = {a:1, b:2};
console.log(obj1 == obj2);
console.log(obj1 = obj2);
console.log(obj1 == obj2);
因為obj1和obj2是對象,屬于引用類型。所以變量obj1和obj2只是儲存著內存的地址指針。
第一次比較的時候obj1和obj2的指向不同的地址,輸出false
然后 obj2的地址指針賦值給了obj1,覆蓋了obj1原本的地址指針
第二次比較時,obj1和obj2的地址指針已經一樣了,所以輸出true
3. 如下代碼輸出什么? 為什么
var a = 1
var b = 2
var c = { name: '饑人谷', age: 2 }
var d = [a, b, c]
var aa = a
var bb = b
var cc = c
var dd = d
a = 11
b = 22
c.name = 'hello'
d[2]['age'] = 3
console.log(aa) // 1 即便后面a又重新賦值成11但是number做為基本數據類型,其賦值后,只是相當于拷貝了一個值的副本并重新創建了一個棧內存空間
console.log(bb) // 2
console.log(cc) // {name: "hello", age: 3} cc和c都有同樣的一個對象指針或地址,即兩者尋址最終都會到達同樣一個堆內存中
console.log(dd) //[1, 2, {name: "hello", age: 3}] 通過數組索引改變了原對象c中的age屬性
4. 如下代碼輸出什么? 為什么
var a = 1
var c = { name: 'gao', age: 2 }
function f1(n){
++n
}
function f2(obj){
++obj.age
}
f1(a)
f2(c)
f1(c.age)
console.log(a) // 1
console.log(c) // { name: 'gao', age: 3 }
當執行f1(a)時,a將他的值1賦給n,函數執行后 n為2 ,a并沒有受到影響,值不變
當執行f2(c)時,c將自身的引用鏈接賦給了obj,obj對引用的數據的age屬性的值進行了更改,也就是c對象也同時改變值,age屬性的值變為3
5. 過濾如下數組,只保留正數,直接在原數組上操作
var arr = [3,1,0,-1,-3,2,-5]
function filter(arr){
for(var i = 0; i < arr.length; i++){
if(arr[i] < 1){
arr.splice(i,1);
i -= 1;
}
}
}
filter(arr)
console.log(arr) // [3,1,2]
6. 過濾如下數組,只保留正數,原數組不變,生成新數組
1.
var arr = [3,1,0,-1,-3,2,-5];
var arr2 = arr.slice();
function filter(arr2) {
for(var i=0;i<arr2.length;i++) {
if(arr2[i]<=0) {
arr2.splice(i,1);
filter(arr2);
}
}
}
filter(arr2);
console.log(arr2) // [3,1,2]
console.log(arr) // [3,1,0,-1,-2,2,-5];
2.
var arr = [3,1,0,-1,-3,2,-5];
var arr2 = arr.filter(function(elem){
return (elem > 0);
});
console.log(arr2) // [3,1,2]
console.log(arr) // [3,1,0,-1,-2,2,-5];
7. 寫一個深拷貝函數,用兩種方式實現
1.
function deepCopy(obj) {
var newObj = {};
for (var key in obj) {
//只賦值對象自己的屬性,原型上的屬性不賦值
if (obj.hasownproperty(key)) {
//由于如果屬性值是引用類型就不能直接賦值,所以我們需要判斷一下屬性的類型
//由于typeof null返回值也是object,所以不能直接用typeof obj[key] === 'object'來判斷
if (typeof obj[key] === 'number' || typeof obj[key] === 'string' || typeof obj[key] === undefined || typeof obj[key] === null || typeof obj[key] === 'boolean') {
newObj[key] = obj[key];
}else {
//當再次遞歸之后,返回的是
newObj[key] = deepCopy[obj[key]];
}
}
}
return newObj;
}
2.
借助JSON: 利用json.stringify()將對象轉換為字符串,然后再利用json.parse()將字符串轉換為對象
function deepCopy(obj) {
return newObj = JSON.parse(JSON.stringify(obj));
}