1. JS由哪几部分组成

  • ECMAScript语言核心:由 ECMA-262 定义,提供核心语言功能,ECMAScript 是由ECMA (欧洲计算机制造商协会)国际进行标准化的一门编程语言,ECMAScript 作为各自 JavaScript 实现的基础。
  • DOM文档对象模型:(Document Object Model,简称DOM),提供访问和操作网页内容的方法和接口,是W3C组织推荐的处理可扩展标记语言的标准编程接口。

DOM扩展:Selectors API、Element Traversal API 和 HTML5 扩展。

DOM2 和 DOM3 中新增的 DOM 属性、方法和对象

  • BOM浏览器对象模型:(Browser Object Model,简称BOM),提供与浏览器交互的方法和接口, 通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。

BOM对象:window、document、location、navigator 和 screen。

  1. JS数据类型

  • 基本数据类型:
  1. 布尔型(Boolean): true/false
  2. 数值型(Number):整数和浮点数值
  3. 字符串型(String):字符串,
  4. Null类型:空值,null值表示一个空对象,typeof返回空对象,object
  5. Undefined类型:未定义值,使用var声明变量但给变量赋值时,他的值就是undefined,typeof返回undefined。
  6. symbol:ES6新增数据类型
  7. bigint:ES11新增数据类型,解决精度问题
  • 引用数据类型:
  1. Object 类型
  2. Function 类型
  • 基本类型和引用类型的区别:
  • 基本类型存放在栈内存中
  • 引用类型存放在堆内存中,,指针在栈内存
  • null和undefined的区别:

    • null表示没有开辟空间(js会自动回收空间),空值。
    • undefined表示开辟了空间但是没有赋值,未定义。
    • null默认转换成number类型是0,undefined是NaN(非数值是一个特殊的数值)
  1. 检测数据类型方法

  2. typeof:检测基本数据类型(除了null),返回字符串

    1. 缺点:不能细分对象,不能区别数组和对象
    2. 原理:所存的值在内存都是按二进制储存
  3. instanceof:检测实例,判断一个对象是否是一个类的实例,判断复杂引用数据类型

    1. 缺点:不能正确判断基本数据类型
  4. constructor:检测构造函数
  5. Object.prototype.toString.call:通过原型链判断,返回[object Xxx]
  6. Array.isArray:检测数组
  7. 数据结构在项目中实际应用:

数组

树形结构:导航栏,菜单栏 输入框链式调用

队列

hash

链表

集合

  1. 堆栈问题,进栈出栈

https://www.bilibili.com/video/BV1U5411Y7k7?p=2

  1. 栈内存:是浏览器给代码提供的执行的环境
  2. EC执行上下文:代码自己执行时所在的环境
  3. ECStack:执行环境栈,栈内存
  4. 堆内存:存放属性和方法
  5. 作用域(执行上下文): 全局作用域,函数作用域,块级作用域
  6. GO:全局对象:浏览器把属性方法放到单独内存=>堆内存(Heap),任何开辟的内存都有一个16进制的内存地址,window代表全局对象
  7. VO(G):全局变量对象,存放变量,当前上下文
  8. AO:私有活动变量对象

进栈:形成的全局执行上下文进入到栈内存中执行

全局不会出栈,私有的会出栈,先进后出

栈溢出,内存优化机制

AST语法解析 词法解析

变量顺序:var a = 123;

  1. 先创建值,在栈内存中存放。
  2. 创建变量
  3. 变量和值关联

对象顺序: 所有的指针赋值都是指针的关联指向

  1. 创建一个堆内存
  2. 把键值对存放在堆内存中
  3. 堆内存地址放在栈中

基本类型:值类型

引用类型:引用地址

  1. 作用域

  • 作用域:ES5全局作用域,函数作用域,ES6块级作用域
  1. 闭包

  • 概念:指的是能够访问另一个函数作用域的变量的函数,设计私有的方法和变量。
  • 优点:

    • 缓存。将变量隐藏起来不被 GC 回收,避免全局变量的污染
    • 实现柯里化。利用闭包特性完成柯里化。
  • 缺点:

    • 内存消耗。闭包产生的变量无法被销毁。
    • 性能问题。由于闭包内部变量优先级高于外部变量,所以需要多查找作用域链的一个层次,一定程度影响查找速度。

https://mp.weixin.qq.com/s?__...

  1. 函数柯里化

https://www.jianshu.com/p/69fa332823bf

  • 概念:将一个多参数的函数转化为单参数函数的方法
  • 作用:柯里化函数主要起到预处理的作用;
  • 好处:参数复用,提前确认,延迟允许
  1. 可枚举和不可枚举

  2. 可枚举性:对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。描述对象的enumerable属性,称为“可枚举性”,如果该属性为false,就表示某些操作会忽略当前属性。规避掉for...in操作。
  • 在JavaScript中,对象的属性分为可枚举和不可枚举之分,它们是由属性的enumerable值决定的。可枚举性决定了这个属性能否被for…in查找遍历到。
  • 基本包装类型的原型属性是不可枚举的,如Object, Array, Number等
  • Object对象的propertyIsEnumerable()方法可以判断此对象是否包含某个属性,并且这个属性是否可枚举。
  1. 实例对象,构造函数,原型,原型链,链式调用

  • 原型链:构造函数,原型prototype,constructor组成

实例的contructor = 构造函数

不同实例的函数不相等

普通对象 函数对象

普通函数用于创建一个类对象

函数对象才有 prototype

普通对象 函数对象都有__proto__

隐藏属性contructor

const Person = new Function()

  1. 怎么实现原型链继承,ES5/ES6继承

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

https://kaiwu.lagou.com/course/courseInfo.htm?courseId=601#/detail/pc?id=6176

  1. 原型链继承

缺点:孩子改了 父亲也改了

  1. 构造函数继承(借助 call)

缺点:父类原型中的方法无法使用

ES5: User.call(this, )

ES6: class extends

  1. 事件冒泡,事件捕获,事件委托/事件代理,DOM事件流

  • 事件捕获(父级找子级):是从document到触发事件的那个节点,即自上而下的去触发事件。
  • 事件冒泡(子级找父级,更常用):事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发,自下向上。
  • 事件委托(定义共同父级元素):当有多个类似的元素需要绑定事件时,一个一个去绑定即浪费时间,又不利于性能,这时候就可以用到事件委托,给他们的一个共同父级元素添加一个事件函数去处理他们所有的事件,然后根据evt.target找到最终的事件源
  • 阻止事件委托和冒泡:在事件函数中执行event.stopPropagation()
  • 执行顺序:捕获>冒泡
  • addEventListener():false是冒泡,true是捕获
  • 事件流:

事件委托:捕获和冒泡允许我们实现一种被称为 事件委托 的强大的事件处理模式。

先捕获再冒泡

  1. 深拷贝和浅拷贝

相同点:

  • 深拷贝和浅拷贝都只针对引用数据类型

区别:

  • 浅拷贝:拷贝的是指针,共享内存,基本数据类型的值和引用数据类型的指针
  • 深拷贝:开辟新的栈,不共享,修改新对象时不会修改原对象,

浅拷贝实现:

  1. Object.assign(target, ...sources) :目标对象,多个来源对象
  • 一级属性深拷贝 二级属性浅拷贝
  • 缺点:

  1. 扩展运算符 let cloneObj = {...obj}

  1. concat拷贝数组

  1. slice拷贝数组 arr.slice(begin, end)

深拷贝实现:

  1. JSON.parse(JSON.stringify(a)):

缺点:不能对函数遍历

  1. 手写
  2. 改进版 Reflect.ownKeys
  3. 递归浅拷贝
  4. 长轮询和短轮询

  • 长轮询,即在客户端发起请求后,服务器端要判断是否有新的数据要返回,如果没有新数据,则保持请求,直到有新数据的时候再返回给客户端,当客户端收到返回信息后,再进行下一次请求。
  • 短轮询,即在客户端发起请求后,服务器端无论是否有新数据,都会响应该请求,并返回给客户端
  1. 尾调用和尾递归

  2. 尾调用:指某个函数的最后一步是调用另一个函数。

尾调用优化:只保留内层函数的调用帧,safari支持,chrome,firefox不支持。

  1. 尾递归:函数调用自身,称为递归。如果尾调用自身,就称为尾递归。 时间复杂度
  2. 尾递归优化:  fibonacci 不会发生栈溢出,节省内存
  3. eventloop事件循环

  • 事件流:JavaScript是单线程语言,执行分为同步任务和异步任务。
  • 异步任务分为宏任务和微任务。
  • script本身是宏任务

会先执行这个队列里所有的同步任务 遇到宏微分别加到宏微队列

执行完同步后 再执行微任务队列

微任务队列执行完成后 会依次执行宏任务队列

宏任务队列里的微任务全部执行完毕后 继续下一个宏任务

  • 宏任务:整体代码script,setTimeout,setInterval
  • 微任务:Promise.then,nextTick
  1. 防抖和节流

  • 防抖:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
  • 节流:指定时间间隔内只会执行一次任务。

避免频繁操作。

清除再设置1秒执行。

手写防抖

  1. this指向,

  • obj.f()的调用中,因为运行环境在obj对象内,因此函数中的this指向对象obj;
  • 而在全局作用域下调用 fun() ,函数中的 this 就会指向全局作用域对象window;
  • es5 this指向执行的上下文,apply、call、bind可以改变this指向。
  • es6箭头函数:this始终指向函数声明时所在作用域的this的值。
  1. 有哪些办法可以改变this

  2. apply、call、bind可以改变this指向。

使用 ES6 的箭头函数。

  1. promise

https://mp.weixin.qq.com/s?__...


江文艺
1k 声望67 粉丝