1. Set和Map的区别? Map和Object的区别?
- Set类似于数组,但是它的成员的值都是唯一的,没有重复的值 但是set 认为NaN 与NaN是相等的, 所以通过Set的add方法 对NaN进行多次添加的话,也只会添加成功一个。
- Map类似于对象,是键值对的集合
- Map的键的范围不仅限于字符串了,而Object的键是字符串。如果对同一个键多次赋值,后面的会覆盖前面的
- weakSet: 成员的值必须是对象
- weakMap: 键名必须是对象
2. es6新增的一些数组方法
- Array.from()
- 用于将类似数组的对象和可遍历的对象(包括Set和Map数据结构)转成数组
- 类似数组的对象如: dom操作返回的NodeList集合, 函数内部的arguments对象
// NodeList 对象
let ps = document.querySelectorAll('p');
Array.from(ps).filter(p => {
return p.textContent.length > 100;
});
// arguments 对象
function foo() {
var args = Array.from(arguments);
// ...
}
Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']
let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']
- Array.of()
- 将一组值转为数组
Array.of(1,2,3)// [1,2,3]
- Array.fill() 使用给定的值填充一个数组
[1,2,3].fill(7) // [7,7,7]
- Array.flat() 用于将嵌套的数组拉平,默认拉平一层,可传参指定拉平
[1,2,3,[3,4]].flat() //[1,2,3,3,4]
[1,2,3,[1,[1,2]]].flat(2) // [1,2,3,1,1,2]
- Array.flatMap() 对原数组的每一个成员执行一个函数,然后对返回值组成的数组进行拉平,默认拉平一层,可传参指定拉平的层数
---以下顺带写一下---
- Array.some() 一旦找到符合条件的就会返回true,剩下的不会再遍历
- Array.every() 所有元素都符合条件才会返回true,否则只要有一个不满足的话就会返回false,剩下的也不会再去遍历
3. es6的新特性
-
默认参数
-
多行字符串
-
模板文本
const name = `Your name is ${first} ${last}. `;
- 解构赋值
- 增强的对象文本
- 箭头函数
- Promises
- let const 块级作用域
- class 类
- Modules 模块
4. Promise实现原理
5. Promise.all 和 race的区别
6. 箭头函数和普通函数的区别
- 箭头函数没有this对象,它内部的this,就是该箭头函数定义时上层作用域中的this,普通函数的this对象主要是看他执行时所处的对象
- 因为箭头函数没有this,所以不能作为构造函数,不能使用new命令,普通函数可以
- 箭头函数自身没有arguments, 不能在箭头函数中使用arguments对象,可以使用...rest获取参数,arguments对象是个类数组对象
7. let const var 的区别?
- let声明变量,const声明一个只读的常量
- var声明的变量会进行变量提升,在还没有定义这个变量之前就使用了整个变量不会报错,因为编译完成之后,变量的声明会被提升到作用域的最顶部,而let和const 不会
- 暂时性死区,只要在这个块级作用域里let或者const 声明了整个这个变量 就不会受外部作用域的影响了
- var在全局作用域中声明的变量会被挂在window对象下,作为window的一个属性,而let 和const不会
- const如果定义了一个对象,那么这个对象中的属性是可以被改变的,因为定义的变量指向的内存保存的是这个对象的引用地址,如果改了对象的属性值,并不会改变这个对象在内存中的引用地址,所以这个变量指向的值其实是没有改变的。 const实际保证的是变量指向的那个内存地址所保存的数据不得改动。 如果希望const定义的对象的属性不能被修改怎么办? 可以使用Object.freeze()
const foo = Object.freeze({})
foo.prop = 123; //写不进去
8. 堆和栈的区别?
栈 | 堆 |
---|---|
一种遵循后进先出的有序集合,由编译器自动分配和释放 | 一般由操作人员(程序员)分配释放,如果没有释放就由操作系统进行释放 |
js中基础数据类型存储在栈内存,大小固定并且有序 | js的引用类型数据存储在堆内存中,大小不固定,复杂可变 |
栈内存存储:
变量 | 值 |
---|---|
a | 'hello' |
b | 3 |
c | 对象obj的地址 |
为什么有栈内存和堆内存之分?
- 为了使程序运行时占用的内存最小
- 当一个方法执行时,就会建立自己的内存栈,在这个方法中定义的所有的变量都会被依次放入这个栈内存中,当方法执行结束之后,这块栈内存也会随之销毁(编译器自动释放)。所有在方法中定义的变量都是存在栈内存中。
- 当创建一个对象时,这个对象会被保存在堆内存中,以便反复利用,(因为对象的创建成本比较大,占用的内存交大)
- 堆内存中的对象不会随着方法执行结束而被销毁,因为还可能被另外的变量所引用
- 只有当一个对象没有任何变量引用它时,才会被系统的垃圾回收机制回收
- 闭包中的基本数据类型变量不保存在栈内存中,而是保存在堆内存中,所以在函数执行完毕之后不会被销毁,这也是为什么函数执行完之后,为什么闭包还能引用到函数内的变量
闭包
- 闭包是指有权访问另一个函数作用域中的变量的函数。(js高程设计书上的原话)
- 创建闭包的常见方式就是在一个函数A内部创建另一个函数B,函数B中使用了函数A中的变量,然后return函数B
function A() {
const a = 'hello';
return function() {
const b = a + 'lll'
return b;
}
}
A()() // hellolll
- 当某个函数被调用时,会创建一个执行环境及相应作用域链,然后使用arguments和其他命名参数的值来初始化函数的活动对象。但是在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位...直到作用域链终点是全局执行环境。在函数执行过程中,为读取和写入变量的值,就需要在作用域链中查找变量。
instanceof实现原理
instanceof
通过判断构造函数的prototype
属性是否出现在实例的原型链上。如果出现的话就返回true,否则是false.
[] instanceof Array // true
[] instanceof Object // true
--------------------------------
function a() {}
a instanceof Function // true
a instanceof Object // true
-------------------------------
function Animal(){}
const an = new Animal();
an instanceof Aniaml //true
an instanceof Object // true
实现一个instanceof
function Animal(){}
const an = new Animal();
const isInstance = myInstanceof(an, Animal);
console.log('isInstance=', isInstance);
function myInstanceof(left, right) {
let leftProto = left.__proto__;
let result = false;
while (leftProto) {
if (leftProto === right.prototype) {
result = true;
break
} else {
leftProto = leftProto.__proto__
}
}
return result;
}
new 实现原理
const animal = new Animal(); new 主要做了以下工作:
- 创建一个临时对象
- 绑定原型: 将第一步中创建的临时对象的__proto__指向new 操作符后面的构造函数的prototype属性
- 将this指向这个临时对象 //即构造函数中的this指向这个新对象
- 执行构造函数 //给这个临时对象添加属性
- 返回这个临时对象 这里注意如果构造函数返回对象,则返回该对象;否则,返回刚创建的新对象(空对象)。
实现一个new:
function Animal(name, age) {
this.name = name;
this.age = age;
}
Animal.prototype.run = function() { console.log('I can run')}
Animal.prototype.eat = function() { console.log('I can eat')}
const animal = new Animal('小明', 25)
// { name: '小明', age: 25 }
const animal2 = myNew(Animal, '小明', 25);
console.log('animal2=', animal2);
// { name: '小明', age: 25 }
function myNew(constructor, ...arguments) {
const temp = {};
temp.__proto__ = constructor.prototype;
const result = constructor.apply(temp, [...arguments]);
return result instanceof Object ? result : temp;
}
js数据类型?
number string boolean ull undefined object symbol bigInt
如何判断数组?
[] instanceof Array
Object.proptotype.toString.call([])
Array.isArray()