前端面试之JavaScript题目,简单全面(持续更新ing...)

JavaScript面试题

    • 数据类型
      • 1.JavaScript有哪些数据类型,它们的区别?
      • 2.JavaScript中数据类型的检测方式有哪些?
      • 3.判断数组的方式有哪些?
      • 4.null和undefined区别?
      • 5.instanceof操作符的实现及其原理?
      • 6.为什么0.1+0.2 !== 0.3? 如何让其相等?
      • 7.typeof NaN 的结果是什么
      • 8.其它值到字符串的转换规则
      • 9.其他值到数字值的转换规则
      • 10.其他值到布尔类型的值的转换规则
      • 11.Object.is()与比较操作符 "===" "=="的区别
      • 12.如何判断一个对象是空对象
    • ES6
      • 1.ES6有哪些新增特性?
        • 模块化:
        • Class类:
        • 箭头函数:
        • 解构赋值:
        • rest参数:
        • Promise:
        • Map/Set:
        • 模板字符串:
        • 扩展运算符:
        • Async/Await:
        • 迭代器/生成器:
        • Symbol:
      • 2.let const var 的区别
      • 3.如果new一个箭头函数会怎样
      • 4.箭头函数和普通函数的区别
      • 5.for in和for of的区别
    • JavaScript基础
      • 1.new操作符的实现原理
      • 2.数组有哪些原生方法
      • 3.什么是DOM和BOM
      • 4.为什么函数的arguments参数是类数组不是数组?如何遍历类数组?
      • 5.对类数组的理解,如何转化为数组

数据类型

1.JavaScript有哪些数据类型,它们的区别?

类型:JavaScript共有8种数据类型,undefined,null,Boolean,string,number,bigint,symbol,object。
其中symbol和bigint是es6中新增的。
symbol代表创建后独一无二且不可变的数据类型,主要为了解决可能出现的全局变量冲突的问题。
bigint可以安全的存储和操作大整数。
区别
前端面试之JavaScript题目,简单全面(持续更新ing...)_第1张图片

2.JavaScript中数据类型的检测方式有哪些?

  1. 使用typeof判断,其中数组,对象,null,都会被判断为object,其他数据类型可以正确判断。例如typeof 123 'number'
  2. 使用instanceof判断对象的类型,内部运行机制是判断其在原型链中能否找到该类型的原型,因此instanceof只能用于判断引用类型的数据,不能判断基本类型。例如:[] instanceof Array true
  3. 使用constructor判断,但null,undefined不可使用,因为它们不是由对象构建。例如:true.constructor ƒ Boolean() { [native code] }
  4. 使用Object.prototype.toString.call() 使用Object对象的原型方法toString来判断数据类型。例如:Object.prototype.toString.call(123); '[object Number]'

3.判断数组的方式有哪些?

  1. 通过ES6Array.isArray()判断
  2. 通过原型链判断arr.__proto__ === Array.prototype
  3. 通过instanceof判断arr instanceof Array
  4. 通过Object判断 Object.prototype.toString.call(arr);
  5. 通过**isPrototypeOf()**判断 Array.prototype.isPrototypeOf(arr);

4.null和undefined区别?

null代表的是空对象,一般用于返回值可能为对象的变量的初始化。
undefined代表未定义,变量声明了但是未赋其值时返回值可能为undefined

5.instanceof操作符的实现及其原理?

原理:instanceof通过判断构造函数的prototype属性是否出现在对象的原型链中来判断数据是否属于该类型

function myInstanceOf(left, right) {
  let proto = Object.getPrototypeOf(left);
  let prototype = right.prototype;
  while (true) {
    if (!proto) {
      return false;
    }
    if (proto === prototype) {
      return true;
    }
    proto = Object.getPrototypeOf(proto);
  }
}

console.log(myInstanceOf([], Array)); //true
console.log([] instanceof Array); //true
console.log(myInstanceOf(123, Array)); //false
console.log(123 instanceof Array); //false

6.为什么0.1+0.2 !== 0.3? 如何让其相等?

因为计算机是通过二进制的方式存储数据的,所以计算机计算0.1+0.2的时候,实际上是计算的两个数的二进制的和。而这两个数的二进制都是无限循环的数。
如何相等(n1+n2).toFixed(2);

7.typeof NaN 的结果是什么

typeof NaN; // ‘number’
NaN是一个特殊值 它和自身不相等 所以 NaN !== NaN 为true

8.其它值到字符串的转换规则

Null和Undefined 转换成 ‘null’和’undefined’
Boolean类型 true转换’true’ false转换’false’
Number类型的值直接转换 不过极大极小的数字会使用指数形式
Symbol类型的值直接转换,但只允许显式强制类型转换
对于普通对象来说 一般会调用Object的toString()方法(Object.prototype.toString())来返回内部属性[[class]]的值,如”[object Object]“;如果对象有自己的toString()方法,字符串化时就会调用该方法并使用其返回值

9.其他值到数字值的转换规则

Undefined类型的值转换为NaN
Null类型的值转换为0
Boolean类型的值,true转换为1 false转换为0
String类型的值转换如同使用Number()函数进行转换,如果包含非数字值则转换为NaN,空字符串为0
Symbol类型的值不能转换为数字 会报错
对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,再遵循上述的规则将其强制转换为数字

10.其他值到布尔类型的值的转换规则

除了 undefined null false +0 -0 NaN “” 以外 都是true

11.Object.is()与比较操作符 "=" ""的区别

(Object.is(A,B)方法判断两个值是否是相同的值。)
双等号进行相等判断时,如果两边的类型不一致,会先进行强制类型转换后再进行比较
三等号
=)进行相等判断时,如果两边的类型不一致,不会做强制类型转换,直接返回false
使用Object.is进行相等判断时,一般情况下和三等号判断相同,它处理了一些特殊情况,比如-0和+0不再相等,两个NaN是相等的

12.如何判断一个对象是空对象

if(Json.stringify(obj) == '{}'){
	console.log('空对象');
}

if(Object.keys(obj).length < 0){
	console.log('空对象');
}

ES6

1.ES6有哪些新增特性?

● let/const ● 模块化
● Class类 ● 箭头函数
● 解构赋值 ● rest参数
● Promise ● Set/Map
● 模板字符串 ● 扩展运算符
● Async/Await ● 迭代器/生成器● Symbol

模块化:

导入import '模块名称' from '路径';
导出let name = 'te',age = 12; export {name,age}
模块化优点:防止命名冲突,复用性强

Class类:

通过class关键字定义类,使用extends继承,子类必须在构造函数中通过super调用父类参数

箭头函数:

箭头函数内部没有arguments,也没有prototype,所以不能用new关键字调用箭头函数
箭头函数的this指向其父级对象的this

解构赋值:

/**
* 数组的解构赋值
*/
//同时赋值多个变量
let a = 1;
let b = 2;
let c = 3;
let d = 4;
console.log(a, b, c, d); //1 2 3 4

let [e, f, g, h] = [1, 2, 3, 4];
console.log(e, f, g, h); //1 2 3 4

// 解构嵌套数组
const arr = [1, [2, 3, [4, 5, 6]]];
const [a, [b, c, [d, e, f]]] = arr;
console.log(a, b, c, d, e, f); //1 2 3 4 5 6

// 不完全解构
const [a, b, c] = [1, 2];
console.log(a, b, c); //1 2 undefined
const [d, e, [f, g]] = [3, 4, [5]];
console.log(d, e, f, g); //3 4 5 undefined

// 解构的默认值
let [a = true] = [];
console.log(a); //true
/**
* 对象的解构赋值
*/
const { foo, bar } = { foo: 'aaa', bar: 'bbb' };
console.log(foo, bar); //aaa bbb
/**
*  函数参数的解构赋值
*/
function f(options) {
  let name = options.name;
  let age = options.age;
  let sex = options.sex;
  console.log(name, age, sex); //n1 a1 s1
}
function f2({ name, age, sex }) {
  // 经历了 let {name,age,sex} = options
  console.log(name, age, sex); //n2 a2 s2
}
f({ name: 'n1', age: 'a1', sex: 's1' });
f2({ name: 'n2', age: 'a2', sex: 's2' });

// 解构数组类型参数
const arr = [
  [1, 1],
  [2, 2],
  [3, 3],
  [4, 4],
  [5, 5],
];
arr.map(([x, y]) => {
  console.log(x + y); //2 4 6 8 10
});

// 为参数设定默认值
function func({ name = 'test', age = 'test', sex = 'test' }) {
  console.log(name, age, sex); //张三 test test
}
func({ name: '张三' });
/**
* 常见使用场景
*/
// 交换变量
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x, y); // 2 1
// 取函数返回值-数组
function raf() {
  return [1, 2, 3];
}
let [a, b, c] = raf();
console.log(a, b, c); //1 2 3
// 取函数返回值-对象
function rof() {
  return { d: 5, e: 6 };
}
let { d, e } = rof();
console.log(d, e); //5 6
// 函数参数的定义-参数与变量名一一对应
function f1([x, y, z]) {
  console.log(x, y, z); //1 2 3
}
f1([1, 2, 3]);
function f2({ x, y, z }) {
  console.log(x, y, z); //2 1 3
}
f2({ z: 3, x: 2, y: 1 });
// 提取JSON数据
let jsonData = {
  id: 42,
  code: 200,
  data: {
    num: 15,
    price: 32,
    pname: 'tst',
  },
};

let {
  id,
  code,
  data: { num, price, pname },
} = jsonData;
console.log(id, code, num, price, pname); //42 200 15 32 tst

rest参数:

rest用于获取函数参数中可能存在的多余参数,rest参数必须放在最后的位置

function createV() {
  console.log(arguments); //500, 200, 'test'
}
createV(500, 200, 'test');

function createB(width, height, color, ...args) {
  let message = `盒子的宽度=${width},高度=${height},颜色=${color}`;
  console.log(message); //盒子的宽度=200,高度=100,颜色=red
  console.log(args); //[ '测试消息1', '测试消息2' ]
}
createB(200, 100, 'red', '测试消息1', '测试消息2');

Promise:

详见后续

Map/Set:

Map和Set属于ES6新增加的对象
Map 对象用于保存键值对,任何JS支持的值都可以作为key或value
与对象不同的是:

  1. Object的键只能是字符串或者ES6的symbol值,而Map可以是任意值
  2. Map对象有一个size值,存储了键值对的个数,而Object对象没有类似属性
// 添加、删除成员
const m = new Map();
const o = { p: 'Hello world' };
m.set(o, 'content');
console.log('m: ', m); // Map(1) { { p: 'Hello world' } => 'content' }
console.log(m.get(o)); //content
console.log(m.has(o)); // true;
console.log(m.delete(o)); // true;
console.log(m.has(o)); // false

//接收一个数组作为参数,运行原理
const map = new Map([
  ['name', 'zhangsan'],
  ['age', '18'],
]);
console.log('map:', map); //map: Map(2) { 'name' => 'zhangsan', 'age' => '18' }
console.log(map.has('name')); //true

let arr = [
  ['name', 'zhangsan'],
  ['age', '18'],
];
const map1 = new Map();
arr.forEach(([key, value]) => map1.set(key, value));
console.log('map1: ', map1); //map1:  Map(2) { 'name' => 'zhangsan', 'age' => '18' }

// map的键和内存地址绑定, k1 k2 值相同但是内存地址不同
let k1 = ['a'];
let k2 = ['a'];
const map3 = new Map();
map3.set(k1, 111).set(k2, 222);
console.log(map3.get(k1)); // 111
console.log(map3.get(k2)); // 222

Map实例的属性
Map.prototype.size():返回Map结构的成员总数
Map实例的方法分为两大类,操作方法和遍历方法
操作方法:
Map.prototype.set(key, value):set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
Map.prototype.get(key):get方法读取key对应的键值,如果找不到key,返回undefined。
Map.prototype.has(key):has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
Map.prototype.delete(key):delete方法删除某个键,返回true。如果删除失败,返回false。
Map.prototype.clear():clear方法清除所有成员,没有返回值。
遍历方法:
Map.prototype.keys():返回键名的遍历器。
Map.prototype.values():返回键值的遍历器。
Map.prototype.entries():返回所有成员的遍历器。
Map.prototype.forEach():遍历 Map 的所有成员。
Map的遍历顺序就是插入顺序

// 操作方法
const map = new Map();
map.set('foo', true);
map.set('bar', false);
console.log(map.size); //2

const m = new Map();
m.set('edition', 6); //键是字符串
m.set(262, 'standard'); //键是数字
m.set(undefined, 'nah'); //键是undefined
// 链式写法
let map2 = new Map().set(1, 'a').set(2, 'b').set(3, 'c');

const m2 = new Map();
const hello = () => {
  console.log('hello');
};
m2.set(hello, '123'); //键是函数
console.log(m2.get(hello)); //123

const m3 = new Map();
m3.set('edition', 6);
m3.set(262, 'standard');
m3.set(undefined, 'nah');

console.log(m3.has('edition')); //true
console.log(m3.has(262)); //true
console.log(m3.has(undefined)); //true
console.log(m3.has('123')); //false

m3.delete(262);
console.log(m3.has(262)); //false
console.log(m3.size); //2
m3.clear();
console.log(m3.size); //0

// 遍历方法
const map4 = new Map([
  ['F', 'no'],
  ['T', 'yes'],
]);
console.log('map4: ', map4);

for (let key of map4.keys()) {
  console.log(key); // F T
}
for (let value of map4.values()) {
  console.log(value); // no yes
}
for (let item of map4.entries()) {
  console.log(item[0], item[1]); // F no, T yes
}
// 或者
for (let [key, value] of map4.entries()) {
  console.log(key, value); // F no, T yes
}

// map转数组
const map5 = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);
console.log([...map5.keys()]); //[ 1, 2, 3 ]
console.log([...map5.values()]); //['one', 'two', 'three']
console.log([...map5.entries()]); //[ [ 1, 'one' ], [ 2, 'two' ], [ 3, 'three' ] ]
console.log([...map5]); //[ [ 1, 'one' ], [ 2, 'two' ], [ 3, 'three' ] ]

const map6 = new Map().set(1, 'a').set(2, 'b').set(3, 'c');
let newMap1 = new Map(
  [...map6].filter(([key, value]) => {
    return key < 3 && value != 'b';
  })
);
console.log('newMap1: ', newMap1); //newMap1:  Map(1) { 1 => 'a' }

let newMap = new Map(
  [...map6].map(([key, value]) => {
    return [key * 2, '_' + value];
  })
);
console.log('newMap: ', newMap); //newMap:  Map(3) { 2 => '_a', 4 => '_b', 6 => '_c' }

map6.forEach((value, key, mapS) => {
  console.log('Key: %s, Value: %s', key, value);
  // Key: 1, Value: a
  // Key: 2, Value: b
  // Key: 3, Value: c
});

// map转换为数组
const map5 = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);
console.log('[...map5]: ', [...map5]); //[...map5]:  [ [ 1, 'one' ], [ 2, 'two' ], [ 3, 'three' ] ]
let newArr = [];
for (let [key, value] of map5.entries()) {
  newArr.push(key);
  newArr.push(value);
}
console.log('newArr: ', newArr); //[ 1, 'one', 2, 'two', 3, 'three' ]

// 数组转为Map
const map6 = new Map([
  [1, 2],
  [3, 4],
]);
console.log('map6: ', map6); //map6:  Map(2) { 1 => 2, 3 => 4 }

// Map转为对象 如果所有 Map 的键都是字符串,它可以无损地转为对象。
function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [key, value] of strMap) {
    obj[key] = value;
  }
  return obj;
}
const myMap = new Map().set('yes', true).set('no', false);
strMapToObj(myMap);
console.log('myMap: ', myMap); //myMap:  Map(2) { 'yes' => true, 'no' => false }

Set 类似于数组,但其成员值都是唯一的,没有重复的值,Set内部值判断类似于===所以5和’5’是两个不同值,在Set内部 NaN等于自身,所以Set实例内只会存在一个NaN。

 // 数组去重
const s = new Set();
[2,3,4,5,5,2,2,].forEach(x => s.add(x))
console.log(s)
for(let i of s){
  console.log(i);//2 3 4 5
}
let arr = [1,2,2,3,4,5,5,4,4,2,1]
let t = new Set(arr);
console.log('t: ', t);//t:  Set(5) {1, 2, 3, 4, 5}

// 字符串去重
let str = 'aaabbcscdsa';
let s1 = [...new Set(str)].join('');
console.log('s1: ', s1);//s1:  abcsd

// NaN
let set3 = new Set();
let a = NaN;
let b = NaN;
set3.add(a);
set3.add(b);
console.log(set3);//Set(1) {NaN}

Set实例的属性
Set.prototype.constructor:构造函数,默认就是Set函数
Set.prototype.size:返回Set实例的成员总数
Set的实例方法分为两大类,操作方法和遍历方法
操作方法:
Set.prototype.add():添加某个值,返回Set结构本身。
Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。(会改变原有结构)
Set.prototype.has(value):返回一个布尔值,代表该值是否为Set的成员。
Set.prototype.clear():清除所有成员,没有返回值。
遍历方法:
Set.prototype.keys():返回键名的遍历器
Set.prototype.values():返回键值的遍历器
Set.prototype.entries():返回键值对的遍历器
Set.prototype.forEach():使用回调函数遍历每个成员
因为set是类似数组的结构,所以keys和values返回值其实一样。

let set = new Set(['red', 'red', 'green', 'yellow']);
for (let value of set.keys()) {
  console.log(value); // red green yellow
}
for (let value of set.values()) {
  console.log(value); // red green yellow
}
for (let en of set.entries()) {
  console.log(en); // [ 'red', 'red' ]['green', 'green'][('yellow', 'yellow')];
}
set.forEach((ele) => console.log(ele)); // red green yellow

// 遍历的应用
let set1 = new Set(['red', 'green', 'yellow']);
let arr = [...set1];
console.log(arr); //[ 'red', 'green', 'yellow' ]
// 去重
let arr2 = [1, 3, 4, 5, 2, 31, 31, 31, 1, 2, 3];
let unique = new Set(arr2);
console.log(unique); //Set(6) { 1, 3, 4, 5, 2, 31 }

模板字符串:

this is ${value}

扩展运算符:

rest用于函数形参 扩展运算符用于实参

const str = ['a', 'b', 'c'];
function printS() {
  console.log(arguments);
}
printS(str); //参数为一个数组,其中包含三个元素
printS(...str); //参数为三个元素

// 数组合并
const s1 = ['a', 'b', 'c'];
const s2 = ['d', 'e'];
let es5 = s1.concat(s2);
console.log('es5: ', es5); //es5: [ 'a', 'b', 'c', 'd', 'e' ]
let es6 = [...s1, ...s2];
console.log('es6: ', es6); //es6: ['a', 'b', 'c', 'd', 'e']

// 数组的克隆
const s3 = [...s2];
console.log('s3: ', s3); //s3:  [ 'd', 'e' ]

// 将伪数组转化为真正的数组
function argToArray() {
  let arr = [...arguments];
  return arr;
}
let s4 = argToArray(1, 2, 3, 4);
console.log('s4: ', s4); //s4:  [ 1, 2, 3, 4 ]

Async/Await:

详见Async/Await

迭代器/生成器:

未完待续

Symbol:

未完待续

2.let const var 的区别

let是块级作用域,var变量在函数外声明是全局作用域,let在变量未声明之前使用会直接报错,var不会;let禁止重复声明,var可以重复声明;变量在函数内部是局部作用域,变量仅在函数内生效。
const 一.const为常量声明方式,声明变量时必须初始化,后面出现的代码不能再修改该常量的值。 二.const实际上保证的并不是变量的值不得改动,而是指向变量的那个内存地址不得改动,所以定义的对象属性值可以改变。

3.如果new一个箭头函数会怎样

箭头函数是es6中提出来的,它没有prototype,也没有自己的this指向,更不可以使用arguments参数,所以不能new一个箭头函数
new操作符的实现步骤如下:
1.创建一个对象
2.将构造函数的作用域赋值给新对象
(也就是将对象的__proto__属性指向构造函数的prototype属性)
3.指向构造函数中的代码,构造函数的this指向该对象
(也就是为这个对象添加属性和方法)
4.返回新对象

function student(name,age){
	this.name = name;
	this.age = age;
}
function createStu(constructor,...args){
	let obj = Object.create(null);
	Object.setPrototypeOf(obj,constructor.prototype);
	let result = constructor.apply(obj,args);
	return result instanceof Object ? result : obj;
}

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

  1. 箭头函数比普通函数更加简洁, 如果没有参数直接写一个()即可,如果有一个参数可以省去参数的括号
  2. 箭头函数没有自己的this 箭头函数中的this指向自己作用域的上一层
  3. 箭头函数继承来的this指向不会改变,call() apply() bind()不能改变箭头函数中this的指向
  4. 箭头函数不能作为构造函数使用 因为箭头函数没有自己的this,且this指向外层的执行环境,且不能改变指向,所以不能当作构造函数使用。
  5. 箭头函数没有prototype

5.for in和for of的区别

for in 用于遍历对象时,得到的值为对象的key;遍历字符串或者数组时,得到的值为下标。
for of 不能遍历对象;遍历数组或者字符串时,得到的每一个值
for of 用于获取键值对的——值
for in 用于获取键值对的——键 value of key in 获取值用of 获取下标、键用in

const obj = {
  a: 1,
  b: 2,
  c: 3,
};
for (let item in obj) {
  console.log(item); // a b c
}
// for (let value of obj) {
//   console.log(value);//报错
// }
const arr = [4, 5, 6];
for (let item in arr) {
  console.log(item); //0 1 2
}
for (let item of arr) {
  console.log(item); //4 5 6
}

const str = 'test';
for (let item in str) {
  console.log(item); //0 1 2 3
}
for (let item of str) {
  console.log(item); //t e s t
}

JavaScript基础

1.new操作符的实现原理

(1)首先创建了一个新的空对象
(2)设置原型,将对象的原型(protp)设置为函数的prototype对象
(3)让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
(4)判断函数的返回值类型,如果是值类型,返回创建的对象;如果是引用类型,就返回这个引用类型的对象。

function student(name, age) {
  this.name = name;
  this.age = age;
}
function createStu(constructor, ...args) {
  // 创建空对象
  let obj = Object.create(null);
  // 将空对象的__proto__ 指向构造函数的prototype
  Object.setPrototypeOf(obj, costructor.prototype);
  // 将obj绑定到构造函数上,便可以访问构造函数中的属性
  let result = constructor.apply(obj, args);//obj.constructor(args);
  // 如果result是一个对象则返回 否则返回obj
  return result instanceof Object ? result : obj;
}

let stu1 = createStu(student, 'rte', '12');
console.log('stu1: ', stu1); //stu1:  student { name: 'rte', age: '12' }

2.数组有哪些原生方法

数组转字符串:toString() join() join可以指定转换为字符串时的分隔符
操作数组 尾部 pop() push() 头部 shift() unshit()
数组连接 concat() 返回的是拼接好的数组 不影响原数组
数组截取 slice() 截取数组一部分返回 不影响原数组
数组插入 splice() 影响原数组
查找特定项索引的方法 indexOf() lastIndexOf()
遍历的 map() forEach() filter()

3.什么是DOM和BOM

DOM是指文档对象模型,它指的是把文档当作一个对象,这个对象主要定义了处理网页内容的方法和接口,DOM的最根本对象的document。
BOM是指浏览器对象模型,它指的是把浏览器当作一个对象来看,这个对象主要定义了与浏览器交互的方法和接口,BOM的核心是window。
window 对象含有 location 对象、navigator 对象、screen 对象等子对象,并且 DOM 的最根本的对象 document 对象也是 BOM 的 window 对象的子对象。

4.为什么函数的arguments参数是类数组不是数组?如何遍历类数组?

arguments是一个对象,它的属性是从0开始依次递增的数字,还有callee和length等属性,与数组相似,但是它却没有数组常见的方法属性,比如forEach,所以它们叫类数组
遍历类数组有三种方法

//一 使用call 将数组的方法应用到类数组上,
function foo() {
  Array.prototype.forEach.call(arguments, (a) => console.log(a));
}

foo(1, 23, 4, 45, 6); // 1 23 4 45 6
// 二 使用 Aarry.form()将类数组转换为数组
function foo() {
  const arrArgs = Array.from(arguments);
  arrArgs.forEach((a) => console.log(a));
}

foo(1, 23, 4, 45, 6); // 1 23 4 45 6

// 三 使用展开运算符将类数组转化为数组
function foo() {
  const arrArgs = [...arguments];
  arrArgs.forEach((a) => {
    console.log('a: ', a);
  });
}

foo(1, 23, 4, 45, 6); // 1 23 4 45 6

5.对类数组的理解,如何转化为数组

// 通过call调用数组的slice方法
Array.prototype.slice.call(arrayLike); //效果相当于arrayLike.slice();
// 通过call调用数组的splice方法
Array.prototype.splice.call(arrayLike,0);
// 通过apply调用数组的concat方法
Array.prototype.concat.apply([],arrayLike);
Array.from(arrayLike);

你可能感兴趣的:(javascript,前端,原型模式)