重點:
一、單線程
js引擎是單線程,模擬多線程(短時間內輪流執行多個任務的片段)
步驟:
1.切分任務
2.將任務隨機排列,組成隊列
3.按順序將任務片段送進js進程
4.js線程執行任務片段
二、數據類型
- 基本數據類型的特點:直接存儲在棧(stack)中的數據
- 引用數據類型的特點:存儲的是該對象在棧中引用,真實的數據存放在堆內存裏
1.原始值是不可改變的,原因如下:
var a = 3;
var b = a;
a = 1;
console.log(a); // 1
console.log(b); // 3
var a = 3;
var b = a;
a = 1;
2.引用值在堆棧中的存放
引用數據類型的特點:存儲的是該對象在棧中引用,真實的數據存放在堆內存裏
var arr1 = [1,2,3,4,5];
var arr2 = arr1;
arr1.push(5);
console.log(arr1); // [1,2,3,4,5,5]
console.log(arr2); // [1,2,3,4,5,5]
arr1 = [1,2];
console.log(arr1); // [1,2]
console.log(arr2); // [1,2,3,4,5,5]
var arr1 = [1,2,3,4,5];
var arr2 = arr1;
當arr1.push(5);時,arr2會跟着arr1一起變化
arr1 = [1,2]
arr1重新賦值,arr2不會跟着改變
三、賦值
賦值:只複製指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。
var obj1 = {
a: 1,
b: 2,
c: [3,4,5],
d: function() { console.log(000); }
}
var obj2 = obj1;
obj2.a = 6;
console.log(obj1); //{a: 6, b: 2, c: Array(3), d: ƒ}
console.log(obj2); //{a: 6, b: 2, c: Array(3), d: ƒ}
四、淺拷貝
淺拷貝:創建一個新對象。如果屬性是基本類型,拷貝的就是基本類型的值;如果屬性是內存地址(引用類型),拷貝的就是內存地址 ,因此如果其中一個對象改變了這個地址,就會影響到另一個對象。
var obj1 = {
a: 1,
b: 2,
c: [3,4,5],
d: function() { console.log(000); }
}
function shallowCopy(obj1) {
var resultObj = {};
for (var prop in obj1) {
if (obj1.hasOwnProperty(prop)) {
resultObj[prop] = obj1[prop];
}
}
return resultObj;
}
var obj2 = shallowCopy(obj1);
obj2.a = 6;
obj2.c[0] = 7;
console.log(obj1); //{a: 1, b: 2, c: [7,4,5], d: ƒ}
console.log(obj2); //{a: 6, b: 2, c: [7,4,5], d: ƒ}
淺拷貝方法:
1.如上的屬性複製方法
2.Object.saaign():
var obj1 = {
a: 1,
b: 2,
c: [3,4,5],
d: function() { console.log(000); }
}
var obj2 = Object.assign({}, obj1);
obj2.a = 6;
obj2.c[0] = 7; // 淺拷貝
console.log(obj1); // {a: 1, b: 2, c: [7,4,5], d: ƒ}
console.log(obj2); // {a: 6, b: 2, c: [7,4,5], d: ƒ}
obj2.c = [8,9,0]; //
console.log(obj1); // {a: 1, b: 2, c: [7,4,5], d: ƒ}
console.log(obj2); // {a: 6, b: 2, c: [8,9,0], d: ƒ}
3.如果是數組,可使用Array.prototype.concat()和Array.prototype.slice(),這兩個方法都不修改原數組
Array.prototype.concat():
var arr1 = [1,[2,3,4],5];
var arr2 = arr1.concat();
arr2[0] = 6;
arr2[1][0] = 7;
console.log(arr1); //[1,[7,3,4],5]
console.log(arr2); //[6,[7,3,4],5]
Array.prototype.slice():
var arr1 = [1,[2,3,4],5];
var arr2 = arr1.slice();
arr2[0] = 6;
arr2[1][0] = 7;
console.log(arr1); //[1,[7,3,4],5]
console.log(arr2); //[6,[7,3,4],5]
五、深拷貝
1.JSON.parse(JSON.stringify()):用JSON.stringify將對象轉成JSON字符串,再用JSON.parse()把字符串解析成對象,一去一來,新的對象產生了,而且對象會開闢新的棧,實現深拷貝。
可以實現數組或對象深拷貝,但不能處理函數
var obj1 = {
a: 1,
b: 2,
c: [3,4,5],
d: function() { console.log(000); }
}
var obj2 = JSON.parse(JSON.stringify(obj1));
console.lpg(obj2); // {a: 1, b: 2, c:[3,4,5]} //d中的函數直接被略去
2.手寫遞歸方法:遞歸方法實現深度克隆原理:遍歷對象、數組直到裏邊都是基本數據類型,然後再去複製,就是深度拷貝
//定義檢測數據類型的功能函數
function checkedType(target) {
return Object.prototype.toString.call(target).slice(8, -1)
}
//實現深度克隆---對象/數組
function clone(target) {
//判斷拷貝的數據類型
//初始化變量result 成爲最終克隆的數據
let result, targetType = checkedType(target)
if (targetType === 'Object') {
result = {}
} else if (targetType === 'Array') {
result = []
} else {
return target
}
//遍歷目標數據
for (let i in target) {
//獲取遍歷數據結構的每一項值。
let value = target[i]
//判斷目標結構裏的每一值是否存在對象/數組
if (checkedType(value) === 'Object' ||
checkedType(value) === 'Array') { //對象/數組裏嵌套了對象/數組
//繼續遍歷獲取到value值
result[i] = clone(value)
} else { //獲取到value值是基本的數據類型或者是函數。
result[i] = value;
}
}
return result
}