재귀 필기 딥 카피
전제:
전체 복사 및 단순 복사는 Object 및 Array와 같은 참조 데이터 유형에만 사용됩니다.
1. 스택 메모리
자세한 내용은 다른 블로그 데이터 유형 및 스택 스토리지를 참조하십시오.
2. 얕은 복사 및 깊은 복사
전체 복사 및 얕은 복사의 개략도는 대략 다음과 같습니다.
단순 복사는 개체 자체가 아닌 개체에 대한 포인터 만 복사하며 이전 개체와 새 개체는 여전히 동일한 메모리를 공유합니다. 그러나 딥 카피는 정확히 동일한 객체를 생성합니다. 새 객체는 원래 객체와 메모리를 공유하지 않습니다. 새 객체를 수정해도 원래 객체로 변경되지 않습니다.
할당과 얕은 복사의 차이점
할당:
개체를 새 변수에 할당 할 때 실제로는 힙의 데이터가 아니라 스택에있는 개체의 주소입니다. 즉, 두 객체가 동일한 저장 공간을 가리키고 어떤 객체가 변경 되더라도 실제로는 변경된 저장 공간의 내용이므로 두 객체가 연결됩니다.
얕은 카피 :
단순 복사본은 개체의 비트 단위 복사본으로 원본 개체의 속성 값과 정확히 일치하는 복사본을 사용하여 새 개체를 만듭니다. 속성이 기본 유형이면 기본 유형의 값이 복사되고, 속성이 메모리 주소 (참조 유형)이면 메모리 주소가 복사되므로 한 개체가이 주소를 변경하면 다른 개체에 영향을줍니다. 즉, 기본 복사 생성자는 개체의 단순 복사 만 수행합니다 (멤버별로 멤버 복사). 즉, 리소스를 복사하지 않고 개체 공간 만 복사합니다.
손으로 쓴 전체 복사 (재귀) :
/**
* 深拷贝
*/
const obj1 = {
age: 20,
name: 'xxx',
address: {
city: 'beijing'
},
arr: ['a', 'b', 'c']
}
const obj2 = deepClone(obj1)
obj2.address.city = 'shanghai'
obj2.arr[0] = 'a1'
console.log(obj1.address.city)
console.log(obj1.arr[0])
/**
* 深拷贝
* @param {Object} obj 要拷贝的对象
*/
function deepClone(obj = {
}) {
if (typeof obj !== 'object' || obj == null) {
// obj 是 null ,或者不是对象和数组,直接返回
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {
}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}
Node.js 데이터 유형 판단
네 가지 방법
typeof 、 instanceof 、 constructor 、 Object.prototype.toString.call () 、 jquery.type ()
1 .typeof
console.log(
typeof 100, //"number"
typeof 'abc', //"string"
typeof false, //"boolean"
typeof undefined, //"undefined"
typeof null, //"object"
typeof [1,2,3], //"object"
typeof {
a:1,b:2,c:3}, //"object"
typeof function(){
console.log('aaa');}, //"function"
typeof new Date(), //"object"
typeof /^[a-zA-Z]{
5,20}$/, //"object"
typeof new Error() //"object"
typeof new Number(100), //'object'
typeof new String('abc'),// 'string'
typeof new Boolean(true),//'boolean'
);
기본 데이터 유형 : 참조 데이터 유형의 숫자, 문자열, 부울, 정의되지 않음 및 함수에서 typeof를 사용하여 데이터 유형을 감지하고 해당 데이터 유형 소문자를 각각 반환 할 수 있습니다.
또 다른 : typeof를 사용하여 생성자가 생성 한 Number, String, Boolean 모두 반환 객체를 감지합니다.
기본 데이터 유형 : null. 참조 데이터 유형 : 배열, 개체, 날짜, RegExp. typeof 감지를 사용할 수 없습니다. 소문자 객체를 반환합니다.
2. 대신에
typeof를 사용하여 판단하는 것 외에도 instanceof를 사용할 수 있습니다. instanceof 연산자는 생성자를 지정하거나이 생성자의 프로토 타입이 주어진 객체의 프로토 타입 체인에 있는지 여부를 결정하는 데 사용되는 특정 유형을 지정해야합니다.
console.log(
100 instanceof Number, //false
'dsfsf' instanceof String, //false
false instanceof Boolean, //false
undefined instanceof Object, //false
null instanceof Object, //false
[1,2,3] instanceof Array, //true
{
a:1,b:2,c:3} instanceof Object, //true
function(){
console.log('aaa');} instanceof Function, //true
new Date() instanceof Date, //true
/^[a-zA-Z]{
5,20}$/ instanceof RegExp, //true
new Error() instanceof Error //true
)
기본 데이터 유형 : 숫자, 문자열, 부울. 리터럴 값은 instanceof로 감지 할 수 없지만 생성자가 생성 한 값은 다음과 같을 수 있습니다.
var num = new Number(123);
var str = new String('dsfsf');
var boolean = new Boolean(false);
또한 null과 undefined는 모두 false를 반환합니다. 이는 해당 유형이 Object가 생성 한 것이 아니라 자체이므로 false가 반환되기 때문입니다.
3 .constructor
생성자는 생성자를 가리키는 프로토 타입 객체의 속성입니다. 인스턴스 객체가 속성을 검색하는 순서에 따라 인스턴스 객체에 인스턴스 속성이나 메서드가없는 경우 프로토 타입 체인에서 검색되므로 인스턴스 객체도 생성자 속성을 사용할 수 있습니다.
유형의 인스턴스 생성자를 출력하면 다음과 같습니다.
console.log(new Number(123).constructor)
//ƒ Number() { [native code] }
Number의 생성자를 가리키는 것을 알 수 있으므로 num.constructor == Number를 사용하여 변수가 Number 유형인지 여부를 확인할 수 있습니다.
var num = 123;
var str = 'abcdef';
var bool = true;
var arr = [1, 2, 3, 4];
var json = {
name:'wenzi', age:25};
var func = function(){
console.log('this is function'); }
var und = undefined;
var nul = null;
var date = new Date();
var reg = /^[a-zA-Z]{5,20}$/;
var error= new Error();
function Person(){
}
var tom = new Person();
// undefined和null没有constructor属性
console.log(
tom.constructor==Person,
num.constructor==Number,
str.constructor==String,
bool.constructor==Boolean,
arr.constructor==Array,
json.constructor==Object,
func.constructor==Function,
date.constructor==Date,
reg.constructor==RegExp,
error.constructor==Error
);
//所有结果均为true
undefined 및 null을 제외하고 다른 유형은 constructor 속성으로 판단 할 수 있습니다.
4. Object.prototype.toString.call ()을 사용하여 객체 유형을 감지합니다.
toString ()을 통해 각 객체의 유형을 얻을 수 있습니다. Object.prototype.toString ()에서 각 객체를 감지하려면 Function.prototype.call () 또는 Function.prototype.apply () 형식으로 호출하여 검사 할 객체를 첫 번째 매개 변수는 thisArg라고합니다.
var toString = Object.prototype.toString;
toString.call(123); //"[object Number]"
toString.call('abcdef'); //"[object String]"
toString.call(true); //"[object Boolean]"
toString.call([1, 2, 3, 4]); //"[object Array]"
toString.call({
name:'wenzi', age:25}); //"[object Object]"
toString.call(function(){
console.log('this is function'); }); //"[object Function]"
toString.call(undefined); //"[object Undefined]"
toString.call(null); //"[object Null]"
toString.call(new Date()); //"[object Date]"
toString.call(/^[a-zA-Z]{5,20}$/); //"[object RegExp]"
toString.call(new Error()); //"[object Error]"
이렇게하면 Object.prototype.toString.call()
변수 유형을 결정하는 가장 정확한 방법이 사용 방법 임을 알 수 있습니다 .
5. 무적의 전능 한 방법 : jquery.type ()
개체가 정의되지 않았거나 null이면 해당하는 "undefined"또는 "null"이 반환됩니다. \
jQuery.type( undefined ) === "undefined"
jQuery.type() === "undefined"
jQuery.type( window.notDefined ) === "undefined"
jQuery.type( null ) === "null"
/*如果对象有一个内部的[[Class]]和一个浏览器的内置对象的 [[Class]] 相同,
我们返回相应的 [[Class]] 名字。 (有关此技术的更多细节。 )*/
jQuery.type( true ) === "boolean"
jQuery.type( 3 ) === "number"
jQuery.type( "test" ) === "string"
jQuery.type( function(){
} ) === "function"
jQuery.type( [] ) === "array"
jQuery.type( new Date() ) === "date"
jQuery.type( new Error() ) === "error" // as of jQuery 1.9
jQuery.type( /test/ ) === "regexp"
其他一切都将返回它的类型“object”
6. 함수를 캡슐화하여 변수의 정확한 유형을 얻을 수도 있습니다.
function gettype(obj) {
var type = typeof obj;
if (type !== 'object') {
return type;
}
//如果不是object类型的数据,直接用typeof就能判断出来
//如果是object类型数据,准确判断类型必须使用Object.prototype.toString.call(obj)的方式才能判断
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
}