單例設計模式及應用
阿新 • • 發佈:2021-01-11
技術標籤:javascript
關於深拷貝淺拷貝,原型,型別校驗,遞迴深拷貝
深拷貝和淺拷貝
如何區分深拷貝與淺拷貝,簡單點來說,就是假設B複製了A,當修改A時,看B是否會發生變化,如果B也跟著變了,說明這是淺拷貝,拿人手短,如果B沒變,那就是深拷貝,自食其力。
資料分為基本資料型別(String, Number, Boolean, Null, Undefined,Symbol)和物件資料型別。
引用資料型別的特點:儲存的是該物件在棧中引用,真實的資料存放在堆記憶體裡
引用資料型別在棧中儲存了指標,該指標指向堆中該實體的起始地址。當直譯器尋找引用值時,會首先檢索其在棧中的地址,取得地址後從堆中獲得實體。
比如淺拷貝:
當b=a進行拷貝時,其實複製的是a的引用地址,而並非堆裡面的值。
而當我們a[0]=1時進行陣列修改時,由於a與b指向的是同一個地址,所以自然b也受了影響,這就是所謂的淺拷貝了。
那,要是在堆記憶體中也開闢一個新的記憶體專門為b存放值,就像基本型別那樣,豈不就達到深拷貝的效果了
實現淺拷貝的方法
(1)for···in只迴圈第一層 // 只複製第一層的淺拷貝 function simpleCopy(obj1) { var obj2 = Array.isArray(obj1) ? [] : {}; for (let i in obj1) { obj2[i] = obj1[i]; } return obj2; } var obj1 = { a: 1, b: 2, c: { d: 3 } } var obj2 = simpleCopy(obj1); obj2.a = 3; obj2.c.d = 4; alert(obj1.a); // 1 alert(obj2.a); // 3 alert(obj1.c.d); // 4 alert(obj2.c.d); // 4
(2)Object.assign方法
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3
實現深拷貝的方法
(1)採用遞迴去拷貝所有層級屬性 function deepClone(obj){ let objClone = Array.isArray(obj)?[]:{}; if(obj && typeof obj==="object"){ for(key in obj){ if(obj.hasOwnProperty(key)){ //判斷ojb子元素是否為物件,如果是,遞迴複製 if(obj[key]&&typeof obj[key] ==="object"){ objClone[key] = deepClone(obj[key]); }else{ //如果不是,簡單複製 objClone[key] = obj[key]; } } } } return objClone; } let a=[1,2,3,4], b=deepClone(a); a[0]=2; console.log(a,b);
(2) 通過JSON物件來實現深拷貝
function deepClone2(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
缺點: 無法實現對物件中方法的深拷貝,會顯示為undefined
(7)如果物件的value是基本型別的話,也可以用Object.assign來實現深拷貝,但是要把它賦值給一個空物件
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign({}, obj); // obj賦值給一個空{}
obj1.a = 3;
console.log(obj.a);// 1
原型
一個可以被複制(或者叫克隆)的一個類,通過複製原型可以建立一個一模一樣的新物件,也可以說原型就是一個模板,在設計語言中更準確的說是一個物件模板
1)原型是定義了一些公用的屬性和方法,利用原型創建出來的新物件例項會共享原型的所有屬性和方法
例項程式碼:
// 建立原型
var Person = function(name){
this.name = name;
};
// 原型的方法
Person.prototype.sayHello = function(){
console.log(this.name+",hello");
};
// 例項化建立新的原型物件,新的原型物件會共享原型的屬性和方法
var person1 = new Person("zhangsan");
var person2 = new Person("lisi");
// zhangsan,hello
person1.sayHello();
// lisi,hello
person2.sayHello();
// 開啟嚴格模式,原型的屬性和方法還是會被原型例項所共享的
"use strict";
// 建立原型
var Person = function(name){
this.name = name;
};
// 原型的方法
Person.prototype.sayHello = function(){
console.log(this.name+",hello");
};
// 例項化建立新的原型物件,新的原型物件會共享原型的屬性和方法
var person1 = new Person("zhangsan");
var person2 = new Person("lisi");
// zhangsan,hello
person1.sayHello();
// lisi,hello
person2.sayHello();
常用的校驗型別方法
typeof 不能校驗 物件 陣列 null
- typefo 不能效驗 物件 陣列 null
- instanceof 誰是誰的例項
- Object.prototype.toString.call 不能判斷例項
- constructor 判斷當前是誰的建構函式
遞迴深拷貝
let arr = [1, 2, 3, 4, 5, { name: 123 }]
// let arr = {name:1234}
Object.prototype.clone = function (data) {
// console.log(typeof(data));
// console.log(Object.prototype.toString.call(data));
// console.log(data instanceof Array);
// console.log(data.constuctor == Object);
if (typeof (data) == 'object') {
// 判斷data的資料型別來建立sum的型別
let sum = data instanceof Array ? [] : {}
// console.log(sum);
for (var i in data) {
// console.log(data[i]);
sum[i] = typeof (data[i]) == 'object' ? clone(data[i]) : data[i]
}
return sum
} else {
return data
}
}
let num = clone(arr)
console.log(num);