js题收集

88 阅读7分钟

1. Set和Map的区别? Map和Object的区别?

  1. Set类似于数组,但是它的成员的值都是唯一的,没有重复的值 但是set 认为NaN 与NaN是相等的, 所以通过Set的add方法 对NaN进行多次添加的话,也只会添加成功一个。
  2. Map类似于对象,是键值对的集合
  3. Map的键的范围不仅限于字符串了,而Object的键是字符串。如果对同一个键多次赋值,后面的会覆盖前面的
  4. weakSet: 成员的值必须是对象
  5. weakMap: 键名必须是对象

2. es6新增的一些数组方法

  • Array.from()
  1. 用于将类似数组的对象和可遍历的对象(包括Set和Map数据结构)转成数组
  2. 类似数组的对象如: 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()
  1. 将一组值转为数组
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的区别

promise.all 和promise.race的区别

6. 箭头函数和普通函数的区别

  1. 箭头函数没有this对象,它内部的this,就是该箭头函数定义时上层作用域中的this,普通函数的this对象主要是看他执行时所处的对象
  2. 因为箭头函数没有this,所以不能作为构造函数,不能使用new命令,普通函数可以
  3. 箭头函数自身没有arguments, 不能在箭头函数中使用arguments对象,可以使用...rest获取参数,arguments对象是个类数组对象

7. let const var 的区别?

  1. let声明变量,const声明一个只读的常量
  2. var声明的变量会进行变量提升,在还没有定义这个变量之前就使用了整个变量不会报错,因为编译完成之后,变量的声明会被提升到作用域的最顶部,而let和const 不会
  3. 暂时性死区,只要在这个块级作用域里let或者const 声明了整个这个变量 就不会受外部作用域的影响了
  4. var在全局作用域中声明的变量会被挂在window对象下,作为window的一个属性,而let 和const不会
  5. const如果定义了一个对象,那么这个对象中的属性是可以被改变的,因为定义的变量指向的内存保存的是这个对象的引用地址,如果改了对象的属性值,并不会改变这个对象在内存中的引用地址,所以这个变量指向的值其实是没有改变的。 const实际保证的是变量指向的那个内存地址所保存的数据不得改动。 如果希望const定义的对象的属性不能被修改怎么办? 可以使用Object.freeze()
const foo = Object.freeze({})
foo.prop = 123; //写不进去

8. 堆和栈的区别?

一种遵循后进先出的有序集合,由编译器自动分配和释放一般由操作人员(程序员)分配释放,如果没有释放就由操作系统进行释放
js中基础数据类型存储在栈内存,大小固定并且有序js的引用类型数据存储在堆内存中,大小不固定,复杂可变

栈内存存储:

变量
a'hello'
b3
c对象obj的地址
为什么有栈内存和堆内存之分?
  1. 为了使程序运行时占用的内存最小
  2. 当一个方法执行时,就会建立自己的内存栈,在这个方法中定义的所有的变量都会被依次放入这个栈内存中,当方法执行结束之后,这块栈内存也会随之销毁(编译器自动释放)。所有在方法中定义的变量都是存在栈内存中。
  3. 当创建一个对象时,这个对象会被保存在堆内存中,以便反复利用,(因为对象的创建成本比较大,占用的内存交大)
  4. 堆内存中的对象不会随着方法执行结束而被销毁,因为还可能被另外的变量所引用
  5. 只有当一个对象没有任何变量引用它时,才会被系统的垃圾回收机制回收
  6. 闭包中的基本数据类型变量不保存在栈内存中,而是保存在堆内存中,所以在函数执行完毕之后不会被销毁,这也是为什么函数执行完之后,为什么闭包还能引用到函数内的变量

闭包

  1. 闭包是指有权访问另一个函数作用域中的变量的函数。(js高程设计书上的原话)
  2. 创建闭包的常见方式就是在一个函数A内部创建另一个函数B,函数B中使用了函数A中的变量,然后return函数B
function A() {
  const a = 'hello';
   return function() {
     const b = a + 'lll'
     return b;
   }
}
A()() // hellolll
  1. 当某个函数被调用时,会创建一个执行环境及相应作用域链,然后使用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 主要做了以下工作:

  1. 创建一个临时对象
  2. 绑定原型: 将第一步中创建的临时对象的__proto__指向new 操作符后面的构造函数的prototype属性
  3. 将this指向这个临时对象 //即构造函数中的this指向这个新对象
  4. 执行构造函数 //给这个临时对象添加属性
  5. 返回这个临时对象 这里注意如果构造函数返回对象,则返回该对象;否则,返回刚创建的新对象(空对象)。

实现一个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

如何判断数组?

  1. [] instanceof Array
  2. Object.proptotype.toString.call([])
  3. Array.isArray()

分别介绍一下原型、原型链、作用域和作用域链的含义和使用场景