前端面试题--02
几道前端经典的面试题
-
对象(数组)的深克隆和浅克隆
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 //深克隆3 使用lodash.cloneDeep实现深克隆 import _ from 'lodash' var obj2 = _.cloneDeep(obj); obj2.c.x = 'obj2'; console.log(obj,obj2) -
几道关于堆栈内存和闭包作用域的题
堆:存储引用类型值的空间
栈:存储基本类型值和指定代码的环境
闭包:保存和保护()
//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'
function A() {
alert(1);
}
function Func() {
A = function () {
alert(2);
};
return this;
}
Func.A = A;
Func.prototype = {
A: () => {
alert(3);
},
};
A(); //1
Func.A(); //1
Func().A();//2
new Func.A();//1
new Func().A(); //3
new new Func().A(); //报错,箭头函数没有原型链,不能new
//问题: 当a为什么时,以下条件成立
var a = ?;
if (a == 1 && a == 2 && a == 3) {
console.log('条件成立');
}
// TO-STRING
// 1.手动添加一个toString方法,每次判断==都会自动调用toString方法
var a = {
i: 0,
toString() {
return ++this.i;
}
};
// a为什么,以下成立
if (a == 1 && a == 2 && a == 3) {
console.log('条件成立');
}
/* var a = [1, 2, 3];
a.toString = a.shift;
if (a == 1 && a == 2 && a == 3) {
console.log('条件成立');
} */
/* 2.数据劫持实现 */
var i = 0;
Object.defineProperty(window, 'a', {
get() {
return ++i;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log('条件成立');
}
/* var a = 0;
Object.defineProperty(window, 'a', {
get() {
// Uncaught TypeError: Cannot redefine property: a
// defineProperty GETER拦截器中不能再次获取当前属性,会死循环
return ++a;
}
});
console.log(a); */
== ,数据类型不一样
1. 对象==字符串, 对象自动调用toString变成字符窜 ['a']=='a'
2. null ==undefind相等,但是和其他值比较不在相等了
3. NaN ==NaN,不相等
4. 剩下的都是转换成数字 '1'==true //true
[10]==10 ,底层转换
[10]自动调用toString为‘10’,然后自动调用number,为10

浙公网安备 33010602011771号