博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript面试知识点
阅读量:6511 次
发布时间:2019-06-24

本文共 4947 字,大约阅读时间需要 16 分钟。

一、Event-Loop,一般出题说执行顺序,有可能问与Node的区别

二、Promise

三、ES6有哪些新特性,Promise/Proxy可能会问

四、this指向,打印

五、变量提升

六、JS判断变量类型

JavaScript 具有七种内置数据类型,它们分别是:

  • null
  • undefined
  • boolean
  • number
  • string
  • object
  • symbol

类型判断常用的方法

  • typeof
  • instanceof
  • Object.prototype.toString
  • constructor

使用 typeof 判断类型

typeof 5 // "number"typeof 'lucas' // "string"typeof undefined // "undefined"typeof true // "boolean"typeof null // "object"const foo = () => 1typeof foo // "function"const foo = {}typeof foo // "object"const foo = []typeof foo // "object"const foo = new Date()typeof foo // "object"const foo = Symbol("foo") typeof foo // "symbol"复制代码

总结:使用 typeof 可以准确判断出除 null 以外的基本类型,以及 function 类型、symbol 类型;null 会被 typeof 判断为 object。

使用 instanceof 判断类型 使用 a instanceof B 判断的是:a 是否为 B 的实例,即 a 的原型链上是否存在 B 构造函数。因此如果使用:

function Person(name) {    this.name = name}const p = new Person('lucas')p instanceof Person复制代码

这里 p 是 Person 构造出来的实例。同时,顺着 p 的原型链,也能找到 Object 构造函数:

p.__proto__.__proto__ === Object.prototypep instanceof Object复制代码

注意:

5 instanceof Number // falsenew Number(5) instanceof Number // true复制代码

我们使用以下代码来模拟 instanceof 原理:

// L 表示左表达式,R 表示右表达式const instanceofMock = (L, R) => {    if (typeof L !== 'object') {        return false    }    while (true) {         if (L === null) {            // 已经遍历到了最顶端            return false        }        if (R.prototype === L.__proto__) {            return true        }        L = L.__proto__    } }复制代码

使用 constructor 和 Object.prototype.toString 判断类型

使用 Object.prototype.toString 判断类型,我们称之为“万能方法”,“终极方法”:

console.log(Object.prototype.toString.call(1)) // [object Number]console.log(Object.prototype.toString.call('lucas')) // [object String]console.log(Object.prototype.toString.call(undefined)) // [object Undefined]console.log(Object.prototype.toString.call(true)) // [object Boolean]console.log(Object.prototype.toString.call({})) // [object Object]console.log(Object.prototype.toString.call([])) // [object Array]console.log(Object.prototype.toString.call(function(){})) // [object Function]console.log(Object.prototype.toString.call(null)) // [object Null]console.log(Object.prototype.toString.call(Symbol('lucas'))) // [object Symbol]复制代码

使用 constructor 可以查看目标的构造函数,这也可以进行类型判断,但也存在着问题,具体请看:

var foo = 5foo.constructor// ƒ Number() { [native code] }var foo = 'Lucas'foo.constructor// ƒ String() { [native code] }var foo = truefoo.constructor// ƒ Boolean() { [native code] }var foo = []foo.constructor// ƒ Array() { [native code] }var foo = {}foo.constructor// ƒ Object() { [native code] }var foo = () => 1foo.constructor// ƒ Function() { [native code] }var foo = new Date()foo.constructor// ƒ Date() { [native code] }var foo = Symbol("foo") foo.constructor// ƒ Symbol() { [native code] }var foo = undefinedfoo.constructor// VM257:1 Uncaught TypeError: Cannot read property 'constructor' of undefined    at 
:1:5var foo = nullfoo.constructor// VM334:1 Uncaught TypeError: Cannot read property 'constructor' of null at
:1:5复制代码

我们发现对于 undefined 和 null,如果尝试读取其 constructor 属性,将会进行报错。并且 constructor 返回的是构造函数本身,一般使用它来判断类型的情况并不多见。

七、继承、闭包

八、深度克隆,函数缓存

参考:

浅克隆

浅克隆之所以被称为浅克隆,是因为对象只会被克隆最外部的一层,至于更深层的对象,则依然是通过引用指向同一块堆内存.

// 浅克隆函数function shallowClone(o) {  const obj = {};  for ( let i in o) {    obj[i] = o[i];  }  return obj;}// 被克隆对象const oldObj = {  a: 1,  b: [ 'e', 'f', 'g' ],  c: { h: { i: 2 } }};const newObj = shallowClone(oldObj);console.log(newObj.c.h, oldObj.c.h); // { i: 2 } { i: 2 }console.log(oldObj.c.h === newObj.c.h); // true复制代码

九、手撕bind/apply/call等

十、var f = function () {} 和 function f () {}的区别

十一、模块化,AMD/CMD的区别

涉及面试题:为什么要使用模块化?都有哪几种方式可以实现模块化,各有什么特点?

使用模块化的好处:

  • 解决命名冲突
  • 提供复用性
  • 提高代码可维护性

模块化的方式

  • 立即执行函数:在早期,使用立即执行函数实现模块化是常见的手段,通过函数作用域解决了命名冲突、污染全局作用域的问题
  • AMD 和 CMD
  • CommonJS
  • ES Module

AMD/CMD的区别

很多人说requireJS是异步加载模块,SeaJS是同步加载模块,这么理解实际上是不准确的,其实加载模块都是异步的,只不过AMD依赖前置,js可以方便知道依赖模块是谁,立即加载,而CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块,这也是很多人诟病CMD的一点,牺牲性能来带来开发的便利性,实际上解析模块用的时间短到可以忽略

为什么我们说两个的区别是依赖模块执行时机不同,为什么很多人认为ADM是异步的,CMD是同步的(除了名字的原因。。。)

同样都是异步加载模块,AMD在加载模块完成后就会执行改模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行

CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的

这也是很多人说AMD用户体验好,因为没有延迟,依赖模块提前执行了,CMD性能好,因为只有用户需要的时候才执行的原因

1、AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块 2、CMD推崇就近依赖,只有在用到某个模块的时候再去require

十二、Object.create({}) 和 new Object()的区别

十三、对JS的看法

参考: JavaScript是一种基于对象(Object)和事件驱动(Event Driven)并具有相对安全性的客户端脚本语言。它最初由网景公司(Netscape)的Brendan Eich设计,是一种动态、弱类型、基于原型的语言,内置支持类。

特点

  • 一种解释性执行的脚本语言。 JavaScript的语法基本结构形式与C、C++、Java十分类似。但在使用前,不像这些语言需要先编译,而是在程序运行过程中被逐行地解释

  • 一种基于对象的脚本语言。

  • 一种简单弱类型脚本语言。

  • 一种相对安全脚本语言。

  • 一种事件驱动脚本语言。

  • 一种跨平台性脚本语言。

优点

  • JavaScript可以使多种任务仅在用户端就可以完成,而不需要网络和服务器的参与
  • JavaScript可以方便地操纵各种页面中的对象,用户可以使用JavaScript来控制页面中各个元素的外观、状态甚至运行方式,JavaScript可以根据用户的需要“定制”浏览器,从而使网页更加友好。

缺点

  • 各浏览器厂商对JavaScript支持程度不同。
  • “Web安全性”对JavaScript一些功能牺牲。

十四、JS 异步编程及常考面试题

涉及面试题:什么是回调函数?回调函数有什么缺点?如何解决回调地狱问题?

转载于:https://juejin.im/post/5cf7721cf265da1b7401ebab

你可能感兴趣的文章
记录一次处理https监听不正确的过程
查看>>
Zabbix使用SMTP发送邮件报警及定制邮件报警内容
查看>>
SCOM 2012 SP1服务器上安装和配置Veeam MP for VMware
查看>>
UDP中转服务器
查看>>
多核编程的四层境界
查看>>
Windows Phone 实用开发技巧(11):让StackPanel中的控件靠右对齐
查看>>
小记如何修改xen模块
查看>>
centos访问windowsxp共享资源指南.
查看>>
实时游戏对战引擎Photon
查看>>
C语言位操作控件属性
查看>>
nginx的安装及基本配置,及多个域名服务
查看>>
Servlet访问postgresql数据库并提取数据显示在前端jsp页面
查看>>
不改一行代码定位线上性能问题
查看>>
定义运算符
查看>>
git管理
查看>>
idea演示
查看>>
告别暗黄皮肤变水嫩皮肤的8个小习惯
查看>>
加强Eclipse代码自动提示的方法
查看>>
【HM】第4课:MySQL入门
查看>>
GNS3-地址重叠环境中部署IPsec
查看>>