1.引用類型; 2.過濾數(shù)組; 3.深淺拷貝方法;
1.引用類型有哪些?非引用類型有哪些
引用類型:
引用類型(Object, Array, Function, Date, Math, RegExp, Error)指的是那些保存在堆內(nèi)存中的對象,變量中保存的實際上只是一個指針,這個指針指向內(nèi)存中的另一個位置,由該位置保存對象。非引用類型(基本數(shù)據(jù)類型):
number,string,boolean,undefined, null.
指的是保存在棧內(nèi)存中的簡單數(shù)據(jù)段.基本類型 == 非引用類型
復(fù)雜類型 == 對象 == 引用類型
2.如下代碼輸出什么?為什么
var obj1 = {a:1, b:2};
var obj2 = {a:1, b:2};
console.log(obj1 == obj2);//輸出:fasle:會比較兩者內(nèi)存地址,發(fā)現(xiàn)內(nèi)存地址不一樣.
console.log(obj1 = obj2);// 輸出 : Object {a: 1,b: 2}
:這一步把obj2的內(nèi)存地址給了obj1,從此兩者共用一份內(nèi)存地址.
console.log(obj1 == obj2);//輸出:ture :因為兩者共用一份內(nèi)存地址了
3.如下代碼輸出什么? 為什么
var a = 1;
var b = 2;
var c = { name: '饑人谷', age: 2 };
var d = [a, b, c];
var aa = a;//a=1
var bb = b;//a=2
var cc = c;
var dd = d;
a = 11;//aa=1:基本類型引用,只會讓a=11,aa和a 是指向兩塊不同的內(nèi)存空間(即指針).不干擾
b = 22;//bb=2
c.name = 'hello';//{name: "hello", age: 2}
d[2]['age'] = 3;//這句把c對象字面量改為{name: "hello", age: 3}
console.log(aa); //1
console.log(bb);//2
console.log(cc);//Object{name: "hello", age: 3} :引用類型中:兩個變量指向同一個堆對象,改變其中一個變量,另一個也會受到影響
console.log(dd);//[1,2,Object{age: 3, name: "hello"}]
4.如下代碼輸出什么? 為什么
var a = 1;
var c = { name: 'jirengu', age: 2 };
function f1(n){
//var n =a;相當于有這步,但并沒有給a開辟新的內(nèi)存.
++n;
}
function f2(obj){
++obj.age;
}
f1(a);//a=1 n=2
f2(c);//c={name: 'jirengu', age: 2 };
f1(c.age);//c={name: 'jirengu', age: 3 };對象a的點語法訪問的是同一個內(nèi)存地址,所以原指針c的age屬性會改變.
console.log(a);//a=1
console.log(c);//Object {name: 'jirengu', age: 3 };
5.過濾如下數(shù)組,只保留正數(shù),直接在原數(shù)組上操作
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); //splice(i,1)會從第i個開始,刪除1個數(shù),用于數(shù)組增刪元素
--i; //當刪除一個元素,arr的長度會減1,但for循環(huán)的i會一直加1,這樣每次刪一個,會漏掉被刪元素后一個的元素的判斷
}
}
}
filter(arr);
console.log(arr); // [3,1,2]
6.過濾如下數(shù)組,只保留正數(shù),原數(shù)組不變,生成新數(shù)組
方法1:
var arr = [3,1,0,-1,-3,2,-5];
function filter(arr){
var newarr = [];
for(var i = 0;i<arr.length;i++ ){
if(arr[i]>0 ){
newarr.splice(i,0,arr[i]);//splice第二個參數(shù)如果設(shè)置為 0,則不會刪除項目,第三個參數(shù)是添加的參數(shù).
}
}
return newarr;
}
var arr2 = filter(arr);
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];
function filter(arr){
var newArr = [];
for(var i = 0; i<arr.length;i++){
if(arr[i]>0){
newArr.push(arr[i]);
}
}
return newArr;
}
var arr1 = filter(arr);
console.log(arr1);
console.log(arr);
方法3:
var arr = [3,1,0,-1,-3,2,-5];
function filter(arr){
var j = 0;
var newarr = [];
for( var i = 0; i < arr.length; i++){
if( arr[i] > 0){
newarr[j] = arr[i];
j++;
}
}
return newarr;
}
var arr2 = filter(arr);
console.log(arr2); // [3,1,2]
console.log(arr); // [3,1,0,-1,-2,2,-5]
7.寫一個深拷貝函數(shù),用兩種方式實現(xiàn)
在JavaScript中,對于Object和Array這類引用類型值,當從一個變量向另一個變量復(fù)制引用類型值時,這個值的副本其實是一個指針,兩個變量指向同一個堆對象,改變其中一個變量,另一個也會受到影響
而引用類型拷貝分為兩種
淺拷貝:拷貝原對象的引用.
深拷貝:是拷貝出一個新的實例,新的實例和之前的實例互不影響.兩份不同的內(nèi)存地址.方法一
function deepCope(obj){
var newObj = {};
for(var key in obj){
//只賦值對象自己的屬性,原型上的屬性不賦值
if(obj.hasOwnProperty(key)){//obj.hasOwnProperty(prop)這個方法可以用來檢測一個對象是否含有特定的自身屬性
if(typeof obj[key] ==== 'number' ||
typeof obj[key] ==== 'string' ||
typeof obj[key] ==== 'undefined' ||
typeof obj[key] ==== 'boolean' ||
obj[key] ==== null){//由于typeof null返回值也是object,所以不能直接用typeof obj[key] === 'object'來判斷
newObj[key] = obj[key];
}else{
newObj[key] = deepCope(obj[key]);//遞歸
}
}
return newObj;
}
- 上述的hasOwnProperty 方法判斷屬性是否存在,下面的例子檢測了對象 o 是否含有自身屬性 prop
o = new Object();
o.prop = 'exists';
function changeO() {
o.newprop = o.prop;
delete o.prop;
}
o.hasOwnProperty('prop'); // 返回 true
changeO();
o.hasOwnProperty('prop'); // 返回 false
- 方法二
下面兩個方法可以實現(xiàn)對象的深復(fù)制.
JOSN對象中的stringify可以把一個js對象序列化為一個JSON字符串,parse可以把JSON字符串反序列化為一個js對象
// 利用JSON序列化實現(xiàn)一個深拷貝
function deepClone(source){
return JSON.parse(JSON.stringify(source));
}
var o1 = {
arr: [1, 2, 3],
obj: {
key: 'value'
},
func: function(){
return 1;
}
};
var o2 = deepClone(o1);
console.log(o2); // => {arr: [1,2,3], obj: {key: 'value'}}