js面试---ES6

1、let、const、var的区别

块级作用域:let和const具有块级作用域,var不存在块级作用域。块级作用域解决了内层变量可能覆盖外层变量,以及用来计数的循环变量泄露为全局变量的问题。

变量提升:var存在变量提升,let和const不存在变量提升(只能在声明后使用,否则会报错)

给全局添加属性:浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但let和const不会。

重复声明:var可以重复声明变量,let和const不可以。

暂时性死区:在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。var声明变量,不存在暂时性死区。

初始值设置:var和let在声明变量时可以不用设置初始值,const在声明变量时必须设置初始值。

指针指向:let和const都是ES6新增语法,let创建的变量是可以更改指针指向的,而const声明的变量是不允许改变指针指向的。

2、const对象的属性可以修改吗

const保证的不是变量的值不能改变,而是变量指向的那个内存地址不能改动。对于基本数据类型的数据,其值就保存在变量指向的那个内存地址,因此等同于常量。

但对于引用类型的数据,变量指向数据的内存地址,保存的是一个指针,const只能保证这个指针是固定不变的,至于它指向的数据结构是不是不可变的,就完全不能控制了。

3、可以new一个箭头函数吗

箭头函数没有自己的prototype,也没有自己的this指向,不能使用arguments参数,所以不能new一个箭头函数。

new操作符的实现步骤:

a、创建一个对象

b、将构造函数的作用域赋给新对象(即将对象的__proto__属性指向构造函数的prototype属性)

c、指向构造函数中的内容,构造函数中的this指向该对象(即为这个对象添加属性的方法)

d、返回新对象

箭头函数无法执行第2、3步。

4、箭头函数与普通函数的区别

a、箭头函数比普通函数更简洁:如果不需要参数,一个空括号即可;如果只有一个参数,可以省略括号;如果有多个参数,用逗号分隔;如果函数体的返回值只有一句话,可以省略大括号;如果函数体不需要返回值,且只有一句话,在关键句前加一个void关键字即可。

javascript 复制代码
let fn = () => void doesNotReturn();

b、箭头函数没有自己的this:箭头函数在自己作用域的上一层继承this,所以箭头函数中this的指向在它定义时已经确定了,后续不会改变。

c、 call()、apply()、bind()等方法不能改变箭头函数的this的指向

d、箭头函数不能作为构造函数使用

e、箭头函数没有自己的arguments

f、箭头函数没有prototype

g、箭头函数不能用作Generator函数,不能用yield关键字

5、扩展运算符的作用及使用场景

a、对象扩展运算符:用于取出参数对象中的所有可遍历属性,拷贝到当前对象中

扩展运算符对对象实例的拷贝属于浅拷贝。

javascript 复制代码
let bar = { a: 1, b: 2 };
let baz = { ...bar }; // { a: 1, b: 2 }

如果用户自定义的属性,放在 扩展运算符后面,则后面的属性会覆盖前面的属性。

javascript 复制代码
let bar = {a: 1, b: 2};
let baz = {...bar, ...{a:2, b: 4}};  // {a: 2, b: 4}

b、数组扩展运算符

可以将数组转为用逗号分隔的参数序列,且每次只能展开一层数组。

javascript 复制代码
console.log(...[1, 2, 3])
// 1 2 3
console.log(...[1, [2, 3, 4], 5])
// 1 [2, 3, 4] 5

将数组转换为参数序列:

javascript 复制代码
function add(x, y) {
  return x + y;
}
const numbers = [1, 2];
add(...numbers) // 3

复制数组:

javascript 复制代码
const arr1 = [1, 2];
const arr2 = [...arr1];  // [1, 2]

合并数组:

javascript 复制代码
const arr1 = ['two', 'three'];
const arr2 = ['one', ...arr1, 'four', 'five'];  // ["one", "two", "three", "four", "five"]

与结构复制结合起来生成数组:

javascript 复制代码
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest  // [2, 3, 4, 5]

如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

将字符串转换为数组:

javascript 复制代码
[...'hello']    // [ "h", "e", "l", "l", "o" ]

使用Math函数获取数组中的特定值:

javascript 复制代码
const numbers = [9, 4, 7, 1];
Math.min(...numbers); // 1
Math.max(...numbers); // 9

6、 Proxy可以实现什么功能

在vue3中,使用Proxy替换Object.defineProperty来实现数据响应式。

Proxy是ES6新增功能,可以用来自定义对象中的操作。

javascript 复制代码
let p = new Proxy(target, handler)

target代表要添加代理的对象,handler用来自定义对象中的操作。

以下是一个简单的例子:

javascript 复制代码
let onWatch = (obj, setBind, getLogger) => {
  let handler = {
    get(target, property, receiver) {
      getLogger(target, property)
      return Reflect.get(target, property, receiver)
    },
    set(target, property, value, receiver) {
      setBind(value, property)
      return Reflect.set(target, property, value)
    }
  }
  return new Proxy(obj, handler)
}
let obj = { a: 1 }
let p = onWatch(
  obj,
  (v, property) => {
    console.log(`监听到属性${property}改变为${v}`)
  },
  (target, property) => {
    console.log(`'${property}' = ${target[property]}`)
  }
)
p.a = 2 // 监听到属性a改变
p.a // 'a' = 2

7、如何提取高度嵌套的对象里的指定属性

javascript 复制代码
const school = {
   classes: {
      stu: {
         name: 'Bob',
         age: 24,
      }
   }
}

方法一:逐层解构

javascript 复制代码
const { classes } = school
const { stu } = classes
const { name } = stu
name // 'Bob'

方法二:嵌套解构

javascript 复制代码
const { classes: { stu: { name } }} = school
       
console.log(name)  // 'Bob'

在解构出来的变量名右侧,通过冒号+{目标属性名}这种形式,进一步解构它,一直解构到拿到目标数据为止。

8、对...参数的理解

扩展运算符被用在函数形参上时,可以把一个分离的参数序列整合成一个数组:

javascript 复制代码
function mutiple(...args) {
  let result = 1;
  for (var val of args) {
    result *= val;
  }
  return result;
}
mutiple(1, 2, 3, 4) // 24

传入 mutiple 的是四个分离的参数,但是如果在 mutiple 函数里尝试输出 args 的值,会发现它是一个数组。

javascript 复制代码
function mutiple(...args) {
  console.log(args)
}
mutiple(1, 2, 3, 4) // [1, 2, 3, 4]

除解构等外,还可以把函数的多个入参收敛进一个数组里。这一点经常用于获取函数的多余参数,或者像上面这样处理函数参数个数不确定的情况。

9、ES6中模板语法

模板语法使字符串的拼接变得更加简单:

javascript 复制代码
var name = 'css'   
var career = 'coder' 
var hobby = ['coding', 'writing']
var finalString = `my name is ${name}, I work as a ${career} I love ${hobby[0]} and ${hobby[1]}`

模板字符串允许用{}的方式嵌入变量,使字符串的拼接更加简单、易读。模板字符串中,空格、缩进、换行都会被保留;且还可以在{}在进行一些简单的计算。

javascript 复制代码
function add(a, b) {
  const finalString = `${a} + ${b} = ${a+b}`
  console.log(finalString)
}
add(1, 2) // 输出 '1 + 2 = 3'

10、ES6中的字符串处理方法

存在性判定:includes、startsWith、endsWith

includes:判断字符串与子串的包含关系

javascript 复制代码
const son = 'haha' 
const father = 'xixi haha hehe'
father.includes(son) // true

startsWith:判断字符串是否以某个字符开头

javascript 复制代码
const father = 'xixi haha hehe'
father.startsWith('haha') // false
father.startsWith('xixi') // true

endsWith:判断字符串是否以某个字符结尾

javascript 复制代码
const father = 'xixi haha hehe'
father.endsWith('hehe') // true

自动重复:可以使用repeat方法来使同一个字符串输出多次(被连续复制多次)

javascript 复制代码
const sourceCode = 'repeat for 3 times;'
const repeated = sourceCode.repeat(3) 
console.log(repeated) // repeat for 3 times;repeat for 3 times;repeat for 3 times;
相关推荐
叫我:松哥17 分钟前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
UestcXiye27 分钟前
面试算法题精讲:求数组两组数差值和的最大值
面试·数据结构与算法·前后缀分解
严格格27 分钟前
三范式,面试重点
数据库·面试·职场和发展
好名字08211 小时前
monorepo基础搭建教程(从0到1 pnpm+monorepo+vue)
前端·javascript
Flying_Fish_roe1 小时前
浏览器的内存回收机制&监控内存泄漏
java·前端·ecmascript·es6
c#上位机1 小时前
C#事件的用法
java·javascript·c#
万物得其道者成1 小时前
React Zustand状态管理库的使用
开发语言·javascript·ecmascript
小白小白从不日白1 小时前
react hooks--useReducer
前端·javascript·react.js
下雪天的夏风2 小时前
TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错
前端·javascript·typescript
diygwcom2 小时前
electron-updater实现electron全量版本更新
前端·javascript·electron