# js 面试题
# 对象拷贝
深拷贝: 通过利用
JSON.parse(JSON.stringify(Object))
来达到深拷贝的目的 但是JSON深拷贝的缺点是undefined
和function
还有symbol
类型是无法进行深拷贝的 如有需要可以自己手动封装函数来达到目的浅拷贝: 通过ES6新特性
Object.assign()
与扩展...
运算符来达到浅拷贝的目的
# js继承
借助寄生组合继承
主要实现原理 B.prototype = Object.create(a.prototype) 继承a
当我们new
关键字创建实例时,会有B
自身的属性和方法以外,还有a
原型上的方法
当实例化对象调用某个方法时会先在自身和原型上查找,然后是在_proto_上一层层查找,这种方式就是原型链
# addEventListener
1.给一个事件绑定多个监听器 2.可以控制触发的阶段(选择冒泡或者捕获)
target.addEventListener(type, listener, options);
target.addEventListener(type, listener, useCapture);
第三个参数可以传入两种形式,boolean和对象
boolean(useCapture) 默认是false 冒泡阶段 options 有三个属性
- capture 默认false,冒泡阶段
- once 默认false 是否只调用一次
- passive 默认true listener不会调用preventDefault()(阻止默认行为)
EventTarget.addEventListener (opens new window)
# class 和 function 的区别
class创建本质上还是基于原型链, 更加符合面向对象的思维
class的静态方法的this,指向类,并非实例
class定义的方法不能使用object.keys遍历
class不能定义私有属性和方法
class只能用类名调用
# 谈谈作用域链机制
https://segmentfault.com/a/1190000018513150 https://www.cnblogs.com/dolphinX/p/3280876.html
# 箭头函数有没有 arguments 对象
浏览器中执行没有arguments
nodejs中执行是有arguments
# 箭头函数和普通函数的区别
语法更加简洁,清晰
箭头函数与普通函数不同,不会有自己的this, 继承this指向外面一层作用域
.call()/.apply()/.bind()无法改变箭头函数中this的指向
没有自己的arguments
箭头函数没有原型prototype
# js 精度丢失问题
由于数据存储在内存中是以二进制的形式存储,而某些值转成二进制会无限循环,由于位数有限,所以无限循环会自动四舍五入
0.1 + 0.2 = 0.30000000000000004
// 0.1 转成二进制会无限循环
// "0.000110011001100110011001100110011001100110011001100..."
# js中不同进制怎么转换
10 进制转其他进制:Number(val).toString([2,8,10,16])
其他进制转成10进制:Number.parseInt("1101110",[2,8,10,16])
# 讲一讲 Promise
Promise是es6的规范
1.Promise有三个状态值,不可逆的,等待态(pedding), 执行态(resolve), 拒绝态(reject) 2.提供了一个then方法。返回是个promise 3.可以链式调用
# 判断数组的几种方法
- es6语法 Array.isArray()
- obj instanceof Array 原型链查找
- obj.constructor === Array 构造函数类型判断
- Object.prototype.toString.call(obj) === '[object Array]'
# 循环有几种方式,是否支持中断和默认情况下是否支持async/await
for 支持中断、支持异步事件
for of 支持中断、支持异步事件
for in 支持中断、支持异步事件
forEach 不支持中断、不支持异步事件
map 不支持中断、不支持异步事件,支持异步处理方法:map 返回promise数组,在使用 Promise.all 一起处理异步事件数组
// 使用async await 处理异步操作
let results = await Promise.all(arr.map(async (item) => {
// 等待异步操作完成,返回执行结果
return await asyncWorker(item);
}));
reduce 不支持中断、不支持异步事件,支持异步处理方法:返回值返回 promise 对象
# 请写出下面三次alert的结果
<script>
var a = 3
function change1 (a) {
a = 4
}
change1(a)
alert(a)
var user = {age: 30}
function change2 (user) {
user.age = 40
}
change2(user)
alert(user.age)
function change3 (user) {
user = {age: 50}
}
change3(user)
alert(user.age)
</script>
结果
- 3 // 原始类型的值赋值,函数中获取的是参数
- 40 // 引用类型的地址传入
- 40 // 函数中的引用类型的重新赋值
# 右侧写出浏览器console执行完左侧代码以后的alert()内容, 提示接下来三行代码都会弹出三次弹窗
function test(a, b) {
alert(b)
return {
test: function (c, a) {
return test(c, a)
}
}
}
code
1. var a = test(100, 200); a.test(300); a.test(400)
2. var b = test(101).test(201).test(401)
3. var c = test(102).test(202, 302); c.test()
200,undefined, undefined
undefined, undefined, undefined
undefined, 302, undefined
# 设置a的值让条件 a==5&& a==8成立
第一种
const a = { value : 2 };
a.valueOf = function() {
return this.value += 3;
};
console.log(a==5 && a== 8)
- 判断类型
- 判断null undefined
- string == number ? string转number
- boolean == any ? boolean转number
- object == string ? number ? symbol ? object 调用valueOf toString
第二种
# Object.defineProperty
有两种创建方式, 数据描述符和存储描述符
两者共享的属性 configurable: false 该属性的描述符才能够被改变, 可删除修改 enumerable: false 可枚举
可选 value: undefined writable: false 可赋值
存储数据符 get: undefined set: undefined
window.a 与b = {a: 1}是有区别的 window.a 挂在在Array反而和创建object一样
var a = {b: 1}
Object.getOwnPropertyDescriptor(a, "b");
{value: 1, writable: true, enumerable: true, configurable: true}
a = 1
Object.getOwnPropertyDescriptor(window, "a");
{value: 1, writable: true, enumerable: true, configurable: false}
- object.defineProperty 有两种,数据描述符和存储描述符
共有参数configurable, enumerable. 数据描述符多了value, writeable, 存储描述符get, set方法。两者不能混用
2.configurable, 是否重复定义,是否delete, enumerable是否遍历, writeable是否重新赋值
3.window.a的configurable默认为false, 但其他定义对象里面属性为true
4.enumerable为false不可遍历
var o = {};
Object.defineProperty(o, "a", { value : 1, enumerable: true });
Object.defineProperty(o, "b", { value : 2, enumerable: false });
Object.defineProperty(o, "c", { value : 3 }); // enumerable 默认为 false
o.d = 4; // 如果使用直接赋值的方式创建对象的属性,则 enumerable 为 true
Object.defineProperty(o, Symbol.for('e'), {
value: 5,
enumerable: true
});
Object.defineProperty(o, Symbol.for('f'), {
value: 6,
enumerable: false
});
for (var i in o) {
console.log(i);
}
// logs 'a' and 'd' (in undefined order)
Object.keys(o); // ['a', 'd']
o.propertyIsEnumerable('a'); // true
o.propertyIsEnumerable('b'); // false
o.propertyIsEnumerable('c'); // false
o.propertyIsEnumerable('d'); // true
o.propertyIsEnumerable(Symbol.for('e')); // true
o.propertyIsEnumerable(Symbol.for('f')); // false
var p = { ...o }
p.a // 1
p.b // undefined
p.c // undefined
p.d // 4
p[Symbol.for('e')] // 5
p[Symbol.for('f')] // undefined
Configurable 属性
# 不使用for或者while, 创建一个长度为120的数组,并且每个元素的值等于数组长度减去它的下标
- from + map
Array.from(new Array(120)).map((item,index)=>(120 - index))
2.from
Array.from(new Array(100), (item, index) => index)
3.reduce
Array.from(new Array(120)).reduce(function (pre, v, i, arr) {
pre.push(arr.length - i)
return pre
}, [])
# 输出以下代码执行结果,大致时间就好
function wait() {
return new Promise(resolve =>
setTimeout(resolve, 10 * 1000)
)
}
async function main() {
console.time();
await wait();
await wait();
await wait();
console.timeEnd();
}
main();
30多秒,由于await同步执行,等待执行函数到下一步
function wait() {
return new Promise(resolve =>
setTimeout(resolve, 10 * 1000)
)
}
async function main() {
console.time();
let a = wait();
let b = wait();
let c = wait();
await a;
await b;
await c;
console.timeEnd();
}
main();
运行时间是10s多一点 等待时间最长的就是整体时间
# map比set区别
set对象类似数组, Map 对象是键值对集合,和 JSON 对象类似,但是 key 不仅可以是字符串还可以是对象
// set
const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 1];
const set = new Set();
arr.forEach(item => set.add(item));
console.log(set); // 1, 2, 3, 4, 5
// 数组快速去重
console.log([...new Set(arr)]); //[1, 2, 3, 4, 5]
// map
var map = new Map();
var obj = { name: '小缘', age: 14 };
map.set(obj, '小缘喵');
map.get(obj); // 小缘喵
map.has(obj); // true
map.delete(obj) ;// true
map.has(obj); // false
# 数据结构,链表和数组区别
添加修改删除数组会影响前后值的变化
链表是存储在内存中
# 浏览器的内核
1.Trident内核 (IE) 2.Gecko内核 (Firefox) 3.WebKit内核 (Safari内核,Chrome内核原型) 4.Blink内核 (Opera)