前端面试集中复习 - JS篇

1. js数据类型,有几种是新增的?

undefined null boolean number string object

symbol  bigInt  -- 新增

symbol  独一无二 且 不可变更 => 用来解决全局变量的冲突和内部变量覆盖

bigInt  用于解决大数据类型,精度问题的优化,可以安全的存储和操作任意精度整数

2. 基础数据类型通常会如何进行分类?使用起来有什么区别?使用过程中你是如何区分他们的?

可以分为:原始数据类型 + 引用数据类型

原始数据类型: undefined null boolean number string

引用数据类型: 对象、数组、函数

效果不同:

        原始数据类型直接赋值后,不存在引用关系
        属性引用关系

存储位置不同:

        栈: 原始数据类型 =>先进后出栈维护结构 =>栈区由编译器自动分配释放 => 临时变量方式

        堆: 引用数据类型 =>堆内存由开发者进行分配=>直到应用结束

原始数据放置在栈中,空间小、大小固定、操作频繁

引用类型数据量大、大小不固定,赋值给的是地址

3. 数据类型转换

        1).isNaN 和Number.isNaN 的区别
            isNaN 包含了一个隐式转化。
                isNaN =>接收参数会先尝试参数转成数值型,不能被转数值的参数 返回true,非数字值传入返回true
            Number.isNaN => 接收参数会先判断参数是否为数字再判断是否为NaN => 不会进行数据类型转换

        2). 其他的类型转换场景
        转换成字符串:
                Null 和 Undefined =>'null''undefined "
                Boolean =>'true''false
                Number =>'数字’大数据 会转换成带有指数形式
                Symbol =>'内容"
                普通对象 =>'[0bject 0bject]'
        转成数字:
                undefined => NaN
                Null => 0
                Boolean =>truel1   false0
                String =>包含非数字的值NaN 空 0
                Symbol => 报错
                对象 =>相应的基本值类型 => 相应的转换
        转成Boolean:
                undefined | null | false | +0-0 | NaN |  "" => false

4. 原始数据类型如何具有属性操作?比如字符串.length 等操作

js的包装类型,原始数据类型在调用方法和属性时,js会在后台隐式地将基本类型转换成对象。

let a = 'hello'

a.length   // 5

js 在收集阶段 Object(a)   String { 'hello' }

// 去包装
let a = 'hello'
let b = Object(a)
let c = b.valueOf() // 'hello'

5. 数组方法

    转换方法: toString()  toLocalString()  join()  

    尾操作: pop()  push()  

    首操作: shift()  unshift()  

    排序: reverse()  sort()  

    连接: concat()  

    截取: slice()  

    插入: splice()  

    索引: indexOf()  

    迭代方法: every()  some()  filter()  map()  forEach()  

    归并: reduce()  

6. 变量提升 & 作用域

现象:无论在任何位置声明的函数、变量,都被提升到模块、函数的顶部

js实现原理:

解析 / 执行,检查语法、预编译,代码中即将执行的变量核函数声明调整到全局顶部,并且赋值为   undefined,再解析上下文,arguments,函数参数,再统一执行预编译。

就产生了全局上下文(变量定义,函数声明),和函数上下文(变量定义,函数声明,this,arguments)

再去执行阶段,按照代码顺序从上而下逐行运行。

变量提升存在的意义?

        提高性能,先提升,编译解析,后面多次使用到该变量或方法,就只需要去头部找到就可以,无需重复解析,这样就会更加灵活,允许补充定义,规避掉一些不必要的报错。

注意:let 和 const 不支持变量提升,会报错

7. 闭包

什么是闭包,闭包的作用?

在一个函数中访问另一个函数作用域中变量的方法。函数外部可以访问到函数内部的变量。跨作用域可以创建私有变量,但是已经运行结束的逻辑,依然会残留在闭包里,使得变量得不到回收,占据内存,容易造成内存泄漏,需要在使用完成时释放掉,将其赋值为null。

题目:闭包改造for循环

for(var i = 0; i< 9; i++) { // let就不会有问题,因为每次循环相当于一个块级作用域,没有变量提升
  setTimeout(() => {
    console.log(i)
  }, i * 1000)
}

// 利用闭包改造
for(var i = 0; i< 9; i++) {
  ((j) => {
    setTimeout(() => {
      console.log(j)
    }, i * 1000)
  })(j)
}

8. JS ES内置对象有哪些?

内置对象

值属性类: Infinity,NaN,undefined,null

函数属性: eval(),parseInt()

对象: 0bject,Function,Boolean,Symbol,Error

数字: Number,Math,Date

字符串: String,RegExp

集合: Map,set,weakMap

抽象控制: promise

映射: proxy

9. instance 区分数据类型的原理?

获取需要验证的_proto,依次在传入类型的构造函数的原型链上查找是否匹配得上

        eg: 2 instanceof Number   // true

        拿“2” 的原型,在 "Number" 的原型链上进行遍历匹配,匹配成功就返回true,否则返回false

    同理可得:

        利用构造函数可以判断数据类型:

        (2).constructor === Number

        ([]).constructor === Array

    问题:用 constructor 的隐患?

        constructor代表的是构造函数指向的类型,是可以被修改的。

判断数据类型还可以用 Object.prototype.toString.call()

        eg: let a = Object.prototype.toString

              a.call(2)     a.call([])

10. 原型 & 原型链

构造函数:是用来新建一个对象的,构造函数内部 有一个属性叫 prototype

prototype 是一个对象,包含共享属性和方法。

使用构造函数创建对象后,对象内部会存在一个指针(__proto__), 这个指针指向构造函数prototype属性的对应值。

链式获取属性规则:对象在获取属性时会优先在自身属性查找,若找不到则会去原型链上继续找,(每个对象都有自己的【__proto__】顺序:对象本身 =>原型对象 =>直到null 终止查找)如果想要跳过自身属性使用原型链的属性,就可以使用 Object.prototype.toString.call()   (见上条)。

11. 异步编程

回调函数 => cb 回调地域

promise => 链式调用,语义不明确

generator => 考虑如何控制执行 co库

async await => 不改变书写习惯,实现看似同步的处理异步代码

promise 手写promise

promise是一个对象,来触发操作

有三种状态: pending  resolved  rejected

两个过程:pending => resolved  /  pending => rejected

promise缺点:无法取消,pending无细分状态

12. 内存和浏览器执行

浏览器输入地址后发生了什么?link:https://blog.csdn.net/weixin_54714100/article/details/136320335?spm=1001.2014.3001.5502

垃圾回收概念:

js具有自动的垃圾回收机制,会找到不再使用的变量,释放其占用的内存空间

两种变量的回收方式:

        局部变量:块级作用域内有效,函数执行完毕并后续不再使用该函数时,释放局部变量,闭包关联的变量无法释放,需手动释放。

        全局变量:全局有效,使用完才会回收。

现代浏览器如何处理垃圾回收?

        标记清除

            存储在内存中的所有变量都会有一个 环境状态 的标记(进入环境,执行环境,离开环境),定期遍历标记参数,销毁带有 离开环境 的变量,释放内存

        引用计数

            跟踪每个值被引用的次数,当一个执行态被使用完毕,就计数减一,直到引用次数变为0,就表示该变量不会再被使用,释放其内存。

减少垃圾的方案

数组优化:清空数组时,赋值一个 空数组 []  length = 0

object 优化:对象尽量复用,减少深拷贝

函数优化:循环中的函数表达式,尽量统一放在外部,这样不必每次解析。

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值