js 相关面试题

1、ES6版本引入了哪些特性?(全部跟着写一遍,理解)

1.1let 和 const 关键字。
1.2箭头函数以及默认参数。
1.3模板字符串。
1.4解构赋值。
1.5Promise
1.6模块化
1.7扩展运算符
1.8Set 和 Map

1.1let 和 const 关键字
//let 和 const 关键字。
const name = '刘玉洁'
let sex = '女'
1.2箭头函数以及默认参数
//箭头函数以及默认参数
const fnOne = (age=19) => {
    return `姓名: ${name},性别: ${sex},年龄${age}`
}
fnOne() // 姓名: 刘玉洁,性别: 女,年龄19
1.3模板字符串
//多行字符串  \n\换行
`
姓名:刘玉洁\n\
性别:女\n\
年龄:25
`
//输出:
//姓名:刘玉洁
//性别:女
//年龄:25
1.4解构赋值
//解构赋值
// 从数组中提取值并赋给变量
let [a,b,c] = [1,2,3];
console.log(a) // 1
console.log(b) // 2
console.log(c) // 3
// 交换变量的值
var x = 1;
var y = 2;
[x, y] = [y, x];
console.log(x); // 输出 2
console.log(y); // 输出 1

// 从对象中提取值并赋给变量
var {name, age} = {name: "Alice", age: 25};
console.log(name); // 输出 "Alice"
console.log(age); // 输出 25
// 为变量指定新的名称
var {name: n, age: s} = {name: "Alice", age: 25};
console.log(n); // 输出 "Alice"
console.log(s); // 输出 25
1.5Promise
 const promise = new Promise((resolve,reject)=>{
  if(true){
    resolve('成功')
  }else{
    reject('失败')
  }
 })
 promise.then(res=>{
  // 成功回调
  console.log(res)
 },(reason)=>{
  // 失败回调, 执行当前失败回调,catch回调将不会执行
  console.log('reason: '+reason)
 }).catch(reject=>{
  // 失败回调
  console.log(reject)
 }).finally(()=>{
  // promise 成功或失败都会执行finally回调
  console.log('finally')
 })

 //Promise.all方法:
//接受一个Promise数组作为参数,并返回一个新的Promise。当所有的Promise都变为成功状态时,新的Promise的状态才会变为成功。
  const promise1 =  new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('1')
      }, 500);
    })
  
  const promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('2')
      }, 2000);
    })
  const promise3 =  new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('3')
      }, 1000);
    })
  var promises = [promise1, promise2, promise3];
  Promise.all(promises).then(function (values) {
    console.log(values)
    // 处理所有Promise的成功状态 只要有一个promise没有返回,或者报错就不会返回
  }).catch(function (reason) {
    console.log('reason'+reason)
    // 处理第一个Promise的失败状态 
  });

//Promise.race方法:接受一个Promise数组作为参数,并返回一个新的Promise。当任意一个Promise变为成功或失败状态时,新的Promise的状态就会变为相应的状态。
// 注意:1.如果同时有一个成功一个失败,会返回成功状态
 Promise.race(promises).then(function (value) {
    console.log(value)
    // 处理第一个Promise的状态
  }).catch(function (reason) {
    console.log('reason',reason)
    // 处理第一个Promise的状态
  }).finally(() => {
    // promise 成功或失败都会执行finally回调(返回第一个)
    console.log('finally')
  })
1.6模块化 export import
// init.js文件声明方法
const time = ()=>{
    return new Date()
}
export default time

// vue 导入使用  
import time from './init.js'
time()
1.7扩展运算符
//JavaScript中的扩展运算符(spread operator)可以用于展开数组或对象。它使用三个点(...)作为语法,可以将数组或对象的元素展开为独立的参数或属性。
在数组中使用扩展运算符可以将一个数组展开为多个独立的元素,例如:
const arr1 = [1, 2, 3]; const arr2 = [...arr1, 4, 5, 6]; console.log(arr2); // [1, 2, 3, 4, 5, 6]

在对象中使用扩展运算符可以将一个对象的属性展开到另一个对象中,例如:
const obj1 = { a: 1, b: 2 }; const obj2 = { ...obj1, c: 3, d: 4 }; console.log(obj2); // { a: 1, b: 2, c: 3, d: 4 }
1.8Set 和 Map(注:Set和Map都是可迭代的,可以使用for...of循环遍历它们的元素)
//Set是一种类似于数组的数据结构,它的成员是唯一且无序的。Set中的元素不会重复,可以用来去除数组中的重复元素。Set提供了一些常用的方法,如add、delete、has等。
const set = new Set();
set.add(1).add(2).add(3).add(4).add(2).add(3).add(1)
console.log([...set]) // [1.2.3.4]

//Map是一种键值对的数据结构,它类似于对象,但键可以是任意类型。Map提供了一些常用的方法,如set、get、has等。
const map = new Map(); map.set('name', 'John'); map.set('age', 25); 
console.log(map.get('name')); // John 
console.log(map.has('age')); // true 
map.delete('age'); 
console.log(map); // Map { 'name' => 'John' }
2、var、const 和 let 的主要区别是什么?(变量提升,作用域,重复声明,变量赋值,声明时初始化代码走一遍)

变量提升:var声明的变量存在变量提升,即在声明之前就可以使用变量。而const和let声明的变量不存在变量提升,必须在声明之后才能使用变量。

作用域:var声明的变量存在函数作用域,即在函数内部声明的变量在函数外部是不可访问的。而const和let声明的变量存在块级作用域,即在块(如if语句、for循环等)内部声明的变量在块外部是不可访问的。

重复声明:var可以重复声明同一个变量,而const和let不允许重复声明同一个变量。

变量赋值:var和let声明的变量可以重新赋值,而const声明的变量是常量,不允许重新赋值。

声明时初始化:var声明的变量和let声明的变量可以不进行初始化,而const声明的变量必须进行初始化。

3.什么是promise和 async-await

Promise是JavaScript中用于处理异步操作的对象。它可以将异步操作封装成一个Promise对象,通过then方法来处理异步操作的结果。Promise对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。当异步操作完成时,Promise对象的状态会从pending变为fulfilled或rejected,并调用相应的回调函数。

async/await是ES8中新增的用于处理异步操作的语法糖。它基于Promise,可以使异步代码看起来像同步代码,更加易读和易写。async函数是一个返回Promise对象的函数,可以在函数内部使用await关键字来等待一个Promise对象的状态变为fulfilled,并返回异步操作的结果。

  async function fn() {
    const data = await new Promise(function (resolve, reject) {
      setTimeout(() => {
        console.log('111111111')
      }, 1000);
    })
    console.log('22222222')
  }
  fn() // 一秒后输出  111111  2222222

注意:
1.await 只能在申明了async 的函数里面使用
2.await 后面必须跟随一个promise 如果跟随不是promise 会被自动转换为立即执行resolved的Promise对象,并将相应的值作为结果返回。

4.什么是闭包?

1.闭包可以理解为一个函数和其相关的引用环境的组合
2.闭包的作用:闭包可以用来创建私有变量和方法,实现模块化的编程。
3.闭包的弊端:内存泄漏,因为闭包会持有外部函数的变量和引用,导致这些变量无法被垃圾回收。因此,在使用闭包时需要注意内存的管理。

5. BOM 是什么?

BOM,也称为浏览器对象模型,用作浏览器的交互介质。默认对象是窗口,所有函数都可以直接调用,也可以通过指定窗口来调用。History、Screen、location,是 Window 的不同属性。

console.log(window)
6. DOM 是什么?

Document Object Model,俗称DOM,代表HTML文档,它用于更改 HTML 文档的内容。

console.log(document)
7.js数据克隆方法
//1.JSON.parse(JSON.stringify(obj));
const copyobj = JSON.parse(JSON.stringify(obj));  // 函数不能clone
//2....运算符
const copyobj = { ...obj }; // 只能clone 第一层
//3.structuredClone方法
const copyobj = window.structuredClone(obj); // 函数不能clone
//4.创建一个函数克隆所有元素
function clone(obj) {
     var o;
     if (typeof obj == "object") {
         if (obj === null) {
             o = null;
         } else {
             if (obj instanceof Array) {
                 o = [];
                 for (var i = 0, len = obj.length; i < len; i++) {
                     o.push(clone(obj[i]));
                 }
             } else {
                 o = {};
                 for (var j in obj) {
                     o[j] = clone(obj[j]);
                 }
             }
         }
     } else {
         o = obj;
     }
     return o;
 } 
8.如何判断数据类型

8.1 typeof:用于判断基本数据类型,返回字符串类型的值

typeof undefined; // "undefined"
typeof true; // "boolean"
typeof 123; // "number"
typeof "hello"; // "string"
typeof BigInt(123); // "bigint"
typeof Symbol("foo"); // "symbol"
typeof {}; // "object"
typeof []; // "object"
typeof null; // "object"

8.2 instanceof:用于判断对象的类型,返回布尔值。

const arr = [1, 2, 3];
arr instanceof Array; // true

const obj = { name: "Tom" };
obj instanceof Object; // true

function Person(name) {
  this.name = name;
}
const person = new Person("Jack");
person instanceof Person; // true

8.3Object.prototype.toString.call():可以判断所有的类型,返回字符串类型的值。

Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(123); // "[object Number]"
Object.prototype.toString.call("hello"); // "[object String]"
Object.prototype.toString.call(BigInt(123)); // "[object BigInt]"
Object.prototype.toString.call(Symbol("foo")); // "[object Symbol]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
9.数组的常用方法
  const list = [1,2,3 ,4];
  // 数组后面新增
  list.push(1)
  console.log(list) // [1, 2, 3, 4, 1]

  // 删除数组最后面一个
  list.pop()
  console.log(list) // [1, 2, 3]

  //数组前面新增
  list.unshift(5,34)
  console.log(list) // [5,34,1, 2, 3, 4]

  //删除数组最前面一个元素
  list.shift()
  console.log(list) // [ 2, 3, 4]

  // splice  改变原数组 , 下标为0开始,截取长度为1,其余参数都为新增参数
  list.splice(0,1,5)
  console.log(list) //[5,1,2,3]

  // slice  原数组不变 , 下标1开始(包括),截取到下标3(不包括)
  const newList = list.slice(1,3)
  console.log(newList) //[2, 3]

  // reverse 改变元数组 反转数组
  list.reverse()
  console.log(list) //[4, 3, 2, 1]

  // join 数组转字符串
  const newList = list.join(',');
  console.log(newList) //1,2,3,4

  // forEach 循环 
  list.forEach((item,index)=>{
      list[index] = ++item    
  })
  console.log(list) //[2, 3, 4, 5]

  // map 不改变原数组,生成新数组 
  const newList = list.map((item, index) => ++item)
  console.log(newList) //[2, 3, 4, 5]

  // filter 过滤返回匹配的所有项生成数组
  const newList = list.filter(item => item > 3)
  console.log(newList) //[4]

  // find 返回匹配的第一项
  const newList = list.find(item => item > 2)
  console.log(newList) //3

  // every 数组元素全部满足条件返回true
  const newList = list.every(item => item >=1)
  console.log(newList) //true

  // some 数组元素有一个满足条件返回true
  const newList = list.some(item => item >=1)
  console.log(newList) //true  

  // reduce 累加器,传入一个函数和初始值
  // 函数里面有两个值
  // preValue 累加后的值
  // curValue 每一项
  const newList = list.reduce((preValue, curValue) =>{
    return preValue+curValue
  },10)
  console.log(newList) //20
10.数组去重的几种方法

10.1 new Set 去重

    const list = [1, 2, 3, 4, 1, 2, 3, 4, 5];
    // new Set 去重
    const oneList = [...new Set(list)];
    console.log(oneList);

10.2 filter 去重

    const list = [1, 2, 3, 4, 1, 2, 3, 4, 5];
    // filter 去重
    const newList = list.filter((item, index, array) => {
      return array.indexOf(item) === index;
    });
    console.log(newList);

10.3 reduce+includes 去重

    const twoList = list.reduce((array, b) => {
        return array.includes(b) ? [...array] : [...array, b];
     }, []);
    console.log(twoList);

10.4 reduce+indexOf 去重

    const twoList = list.reduce((array, b) => {
      const bol = !!~array.indexOf(b);
      return bol ? [...array] : [...array, b];
    }, []);
    console.log(twoList);

10.5 reduce 去重数组对象

   const list = [
      { a: 1, b: 2 },
      { a: 1, b: 2 },
      { a: 1, b: 3 },
    ];
    const twoList = list.reduce((array, b) => {
      const bol = !!~JSON.stringify(array).indexOf(JSON.stringify(b));
      return bol ? [...array] : [...array, b];
    }, []);
    console.log(twoList); // [ { a: 1, b: 2 },   { a: 1, b: 3 }]
11.bind、call、apply 区别

总结:
bind 方法返回一个新的函数,并可以预先绑定上下文和参数。
call 方法立即调用函数,并传递指定的上下文和参数作为参数。
apply 方法立即调用函数,并传递指定的上下文以及参数数组作为参数。

11.1 bind 方法会创建一个新函数,将其绑定到指定的对象,并返回这个新函数。新函数可以在之后的调用中作为普通函数被调用,也可以作为构造函数使用(使用 new 运算符)。bind 方法可以传递参数给原函数,这些参数会预先传入到新函数中。 例如:

const obj = { name: 'John' };
function getName() {
  console.log(this.name);
}
const boundGetName = getName.bind(obj);
boundGetName(); // 输出:John

11.2 call 方法和 apply 方法都可以立即调用一个函数,并且可以显式地设置函数执行时的上下文(this 值)。唯一的区别在于传递参数的方式不同。
11.2.1call 方法接受一个指定的上下文对象和一系列参数作为参数,并将函数立即执行。 例如:

const obj = { name: 'Sarah' };
function sayHello(message) {
  console.log(`${message}, ${this.name}!`);
}
sayHello.call(obj, 'Hello'); // 输出:Hello, Sarah!

11.2.2 apply 方法也接受一个指定的上下文对象和一个参数数组作为参数,并将函数立即执行。不同的是,参数被传递为数组。 例如:

const obj = { name: 'Emily' };
function sayHello(message) {
  console.log(`${message}, ${this.name}!`);
}
sayHello.apply(obj, ['Hello']); // 输出:Hello, Emily!
12 什么是js执行上下文

JavaScript 执行上下文(Execution Context)是 JavaScript 引擎在执行代码时创建的一个环境。每当 JavaScript 代码执行时,都会创建一个执行上下文,并且这些执行上下文被组织为一个执行上下文栈(Execution Context Stack)。

每个执行上下文包含了三个重要的组成部分:
1.变量对象(Variable Object):用于存储变量和函数声明。变量对象可以看作是当前上下文中的作用域链的一部分。在全局执行上下文中,变量对象被称为全局对象(Global Object)。
2.作用域链(Scope Chain):用于解析变量和函数的访问权限。它是由当前执行上下文的变量对象以及其上层执行上下文的变量对象构成的链式结构。
3.this 值(This Value):指向当前执行上下文所属的对象。
JavaScript 的执行上下文可以包括全局执行上下文(Global Execution Context)、函数执行上下文(Function Execution Context)和 eval 函数执行上下文。

全局执行上下文是最顶层的执行上下文,它在代码开始执行时创建,全局变量和函数声明都会被添加到全局执行上下文的变量对象中。

函数执行上下文,在调用函数时创建,每次函数调用都会创建一个新的函数执行上下文,函数参数、局部变量和内部函数都会被添加到函数执行上下文的变量对象中。

eval 函数执行上下文是通过 eval 函数执行代码时创建的,只有在代码含有 eval 函数调用时才会生成 eval 函数执行上下文。

当 JavaScript 引擎执行代码时,它会根据执行上下文栈(Execution Context Stack)的顺序依次执行各个执行上下文,当前执行上下文执行完成后,会弹出执行上下文栈,并开始执行上一个执行上下文,直到最后一个执行上下文执行完毕,整个代码执行过程结束。

通过理解和管理执行上下文,我们可以更好地理解 JavaScript 代码的执行过程,并且能够正确地访问和修改变量、了解作用域规则以及正确理解 this 的指向。

13.this的指向问题(理解下面文章内容)

https://www.jianshu.com/p/c62aa1812c6d

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • 1. 浏览器渲染机制 浏览器采用流式布局模型(Flow Based Layout) 浏览器会把HTML解析成DOM...
    高磊_IT阅读 741评论 0 3
  • 1.JavaScript的数据类型 字符串(String)、数字(Number)、布尔(Boolean)、对空(N...
    潇洒丨阅读 587评论 0 0
  • 内置类型 JS中分为七种内置类型,其中内置类型又分为两大类型: 基本类型 对象(Object) 基本类型有六种: ...
    小白摘葡萄阅读 687评论 0 2
  • 内置类型 JS 中分为七种内置类型,七种内置类型又分为两大类型:基本类型和对象(Object)。 基本类型有六种:...
    C楚辉H阅读 1,715评论 0 2
  • 1.介绍一下JS的数据类型有那些,值是如何存储的? JavaScript一共有8种数据类型,其中有7中基本数据类型...
    淺時咣阅读 537评论 3 7