1、 判断数组方式
数组:
判断是否为数组的几种方式:
在js中判断数据类型有: typeof instanceof constructor Object.prototype.toString.call
typeof:中的缺陷就是在识别数组和对象的时候都返回Object
instanceof:运算符用于检验构造函数的prototype属性是否出现在对象的原型链中的任何位置,返回一个布尔值。 其缺点是prototype属性是可以修改的。
constructor:实例的constructor属性会指向其构造函数,但是如果使用了内联框架ifram,会导致一个存在多个全局环境的问题,ifram中会拥有自己的Array.prototype。 而想要 arr数组 在 arr.constructor === Array 为true 就得必须保证arr是由原始的Array函数创建的。(在instanceof也存在这个问题)
// 这里是typescript代码格式
var arr:(number | string)[] = [];
console.log(arr instanceof Array); // true
console.log(typeof arr); // object
console.log(arr.constructor === Array); //true
//这边还是推荐使用Object.prototype.toString.call 来判断是否为数组
var toStr = Object.prototype.toString;
console.log(toStr.call(arr).slice(8,13)); // Array slice是字符串中的一种方法,不会改变原来的数据,会返还一个子数据,在数组中也可以使用。
// ES5 提出了一个方法Array.isArray(), 缺点就是在es5之前不能使用
console.log(Array.isArray(arr)); // true
2、深拷贝和浅拷贝
可迭代的类型有: 数组、字符串、map、set
可枚举的类型: 对象、数组、字符串
浅拷贝
// 扩展运算符
type o = {
id: number;
}
let arr: (o | number)[] = [1, 2, 3, { id: 1 }];
let arr1 = [...arr];
(arr1[3] as o).id = 3;
console.log((arr[3] as o).id); // 3 当arr1改变了引用类型的值, arr中的也会改变因为它们指向同一个地址。
// 也可以通过 for in 遍历 (for in 用在可枚举的类型中, for of用在可迭代的类型中)
type o = {
id: number;
}
let arr: (o | number)[] = [1, 2, 3, { id: 1 }];
let arr1: (o | number)[] = [];
for(let key in arr) {
arr1[key] = arr[key];
}
(arr1[3] as o).id = 3;
console.log((arr[3] as o).id); // 3
深拷贝
function deepClone (origin,target) {
var toStr = Object.prototype.toString,
arrStr = '[object Array]';
var target = target || (toStr.call(origin) == arrStr ? [] : {});
for (let prop in origin) {
if(origin.hasOwnProperty(prop)) { // 判断prop属性是否是origin自身的而不是其原型链上的
if(origin[prop] !== null && typeof(origin[prop]) == 'object') {
if(toStr.call(origin[prop] == arrStr)) {
target[prop] = [];
}else {
target[prop] = {};
}
deepClone(origin[prop], target[prop])
}else {
origin[prop] = target[prop]
}
}
}
return target;
}