对象(数组)的深克隆和浅克隆
浅度克隆:被克隆得到的对象基本类型的值修改了,原对象的值不会改变
深度克隆:被克隆得到的对象基本类型的值修改了,原对象的值改变
let obj = {
a: 100,
b: [10,20,30],
c: {
x: 10
},
d: /^\d+$/
};
//浅克隆1
let obj2 = {};
for(let key in obj){
if(!obj.hasOwnProperty(key)) break;
obj2[key] = obj[key];
}
console.log(obj2)
console.log(obj === obj2) //false
console.log(obj.c === obj2.c) //true
//浅克隆2
let obj2 = {...obj}
//深克隆1
//函数、日期格式以及正则用JSON.stringify()都会有问题
let obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2)
//深克隆2
function deepClone(obj){
//=>过滤特殊情况
if(obj === null) return null;
if(typeof obj !== ‘Object‘) return obj;
//正则
if(obj instanceof RegExp){
return new RegExp(obj);
}
//日期格式
if(obj instanceof Date){
return new Date(obj);
}
// let newObj = {};
// let newObj = new Object();
//=>不直接创建空对象,目的:克隆的结果和之前保持相同的所属类
let newObj = new obj.constructor;
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = deepClone(obj[key])
}
}
return newObj;
}
let obj2 = deepClone(obj)
console.log(obj2)
console.log(obj === obj2) //false
console.log(obj.c === obj2.c) //false
几道关于堆栈内存和闭包作用域的题
堆:存储引用类型值的空间
栈:存储基本类型值和指定代码的环境
闭包:保存和保护()
//example 1
let a={},b=‘0‘,c=0;
a[b]=‘zhangsan‘;
a[c]=‘lisi‘;
console.log(a[b]); //lisi
//对象的属性名不能重复,作为属性名数字和字符串是一样的
//=>对象和数组的区别?
//example 2
let a = {},
b = Symbol(‘1‘),
c = Symbol(‘1‘);
a[b]=‘zhangsan‘;
a[c]=‘lisi‘;
console.log(a[b]); //zhangsan
//Symbol创建唯一值的
//=>自己实现Symbol?
//example 3
let a = {},
b = {
n: ‘1‘
},
c = {
m: ‘2‘
};
a[b]=‘zhangsan‘;
a[c]=‘lisi‘;
console.log(a[b]); //lisi
//属性名为对象的话,会转化为字符串, Object.tostring() ==> "[object Object]"
//=>Object.prototype.toString()的应用? / valueOf和toString区别?
//example 1
var test = (function(i){
return function(){
alert(i *= 2);
}
})(2);
test(5); //‘4‘ ,alert会转化为字符串
//test为立即执行的自执行函数,形成闭包,引用了上级作用域的参数
//example 2
var a=0,b=0;
function A(a){
A=function(b){
alert(a+b++);
}
alert(a++) //先执行alert(a),然后a自增; ++a和a++的区别
}
A(1);//‘1‘
A(2);//‘4‘
//函数A中的A没有用var声明,就是全局的A,重写了函数A,又形成了闭包
一道关于面对对象面试题所引发的血案(阿里)
对象成员访问级别高,优先执行,new函数级别低,次之执行
function Foo() {
getName = function () {
console.log(1);
};
return this;
}
Foo.getName = function () {
console.log(2);
};
Foo.prototype.getName = function () {
console.log(3);
};
var getName = function () {
console.log(4);
};
function getName() {
console.log(5);
}
Foo.getName(); //2
getName(); //4
Foo().getName(); //1
getName(); //1
new Foo.getName(); //2
new Foo().getName(); //3
new new Foo().getName(); //3
一道面试题让你彻底掌握JS中的EventLoop
async function async1() {
console.log(‘async1 satrt‘)
await async2()
console.log(‘async1 end‘)
}
async function async2() {
console.log(‘async2 end‘)
}
console.log(‘script start‘)
setTimeout(function() {
console.log(‘setTimeout‘)
}, 0)
async1()
new Promise(resolve => {
console.log(‘Promise‘)
resolve()
}).then(function() {
console.log(‘promise1‘)
}).then(function() {
console.log(‘promise2‘)
})
console.log(‘script end‘)
//浏览器是多线程的,js是单线程=>浏览器只给了其一个线程来渲染
//定时器、事件绑定、ajax等属于宏任务,Promise async await等属于微任务。会优先执行微任务
//执行顺序
创建函数async1
创建函数async2
=>‘script start‘
设置定时器 (宏任务A)
函数执行
=> ‘async1 satrt‘
await async2(); 执行async2等待返回的结果 (微任务B)
=> ‘async2 end‘
new Promise的时候会立即把EC函数执行(new 的时候是同步的)
=> ‘Promise‘
resolve() / reject() (微任务C)
=> ‘script end‘
//主栈第一阶段完成
=> B =>‘async1 end‘
=> C =>‘promise1‘
resolve() / reject() (微任务D)
=> D => ‘promise2‘
=> A => ‘setTimeout‘
原文:https://www.cnblogs.com/xiaojiaoya00/p/14624796.html