1、什么是变量提升?如何避免变量提升?
JS在编译阶段的时候,会搜集所有的变量声明并且提前声明变量,而其他的语句都不会改变他们的顺序,因此,在编译阶段的时候,第一步就已经执行了,而第二步则是在执行阶段执行到该语句的时候才执行。。可以使用let
或const
等关键字来避免变量提升,因为这些关键字声明的变量不会被自动提升。
2、简单说一说let、const、var的区别
es6
提出来let、const
,而var
是es5
提出的let
和var
声明的是变量,声明之后可以更改,声明时可以不赋值,const
声明的是常量,必须赋值var
允许重复声明变量,后一个变量会覆盖前一个变量。let
和const
在同一作用域不允许重复声明变量,会报错。var
不存在块级作用域,var
是函数作用域。let
和const
存在块级作用域。let
和const
不存在变量提升,var
声明的变量存在变量提升
3、JS如何实现继承?有哪些实现方法?
以使用原型链、构造函数、组合继承、寄生组合继承等方式来实现继承。
- 使用原型链:通过指定类的prototype原型为指定构造函数,让新实例的原型等于父类的实例。通过原型特性实现继承。原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!
function Parent() {
this.name = 'Tom';
}
function Child() {}
Child.prototype = new Parent();
var child = new Child();
console.log(child.name); // 输出'Tom'
- 使用构造函数:通过修改this指向将父类属性指向子类(使用call、apply),只继承了父类构造函数的属性,没有继承父类原型的属性。每个新实例都有父类构造函数的副本,臃肿。无法实现构造函数的复用。
function Parent() {
this.name = 'Tom';
}
function Child() {
Parent.call(this);
}
var child = new Child();
console.log(child.name); // 输出'Tom'
- 使用组合继承:使用构造和原型组合方式实现,可以继承父类原型上的属性,可以传参,可复用。每个新实例引入的构造函数属性是私有的。调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。
function Parent() {
this.name = 'Tom';
}
function Child() {
Parent.call(this);
}
Child.prototype = new Parent();
var child = new Child();
console.log(child.name); // 输出'Tom'
- 使用寄生组合继承
function Parent() {
this.name = 'Tom';
}
function Child() {
Parent.call(this);
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var child = new Child();
console.log(child.name); // 输出'Tom'
4、解释JavaScript中的this关键字
在JavaScript中,this关键字表示当前执行上下文环境的所有者。在全局上下文环境中,this指向的是window对象。在函数中,this的值取决于函数的调用方式。
- 若函数是作为一个方法调用的,this就指向这个方法所属的对象。
- 若函数是作为函数调用的,this就指向全局上下文环境。
- 在严格模式下,函数的this值为undefined
5、解释一下JavaScript中的严格模式(Strict Mode)是什么,以及它的作用?
严格模式(Strict Mode)
是JavaScript
中的一种执行模式,它可以通过在脚本或函数的顶部添加特定语句来启用。严格模式引入了一些限制和变化,以帮助开发者编写更规范、更安全的JavaScript
代码。
- 消除了一些不合理或不安全的语法和行为:在严格模式下,一些以前被视为有效但容易导致错误的语法或行为会被禁止,从而帮助开发者避免潜在的问题。
- 提升代码的可读性和维护性:严格模式要求变量声明必须使用关键字(如
var
、let
或const
),这样可以避免意外创建全局变量,提高代码的可读性和可维护性。 - 阻止使用一些不推荐的功能:在严格模式下,一些过时的或不推荐使用的功能被废弃或禁止,例如使用
with
语句、使用arguments.callee
访问函数自身等。 - 提升
JavaScript
引擎的优化能力:严格模式下的代码通常比非严格模式下的代码更容易进行静态分析和优化,这可以使JavaScript
引擎更好地执行代码,提高性能。
要在整个脚本中启用严格模式,可以在脚本的顶部添加如下语句:"use strict";
要在函数内部启用严格模式,可以在函数体的顶部添加如下语句:
function myFunction() {
"use strict";
// 函数体中的代码将以严格模式执行
}
6、解释JavaScript中的事件委托
JS的事件委托又称之为事件代理,是一种在父元素上监听事件,然后通过事件冒泡机制来处理子元素的事件的技术。通过事件委托,可以避免为每个子元素都绑定事件处理程序,提高性能并简化代码。
事件委托的实现原理是基于事件冒泡机制。当一个元素上发生了某个事件(如点击事件),事件会从触发元素开始向上冒泡,直到根节点。事件委托利用了事件冒泡的特性,将事件处理程序绑定在父元素上,通过事件冒泡捕获子元素的事件。
- 给父元素绑定事件
- 给父元素定义事件,监听子元素的冒泡事件
- 找到是哪个子元素的事件,通过匿名回调函数的参数e用来接收事件对象,通过target获取触发事件的目标
当有多个列表元素需要绑定事件时,一个一个去绑定即浪费时间,又不利于性能,这时候就可以用到事件委托,给他们的一个共同父级元素添加一个事件函数去处理他们所有的事件情况。
在 javascript 中,页面中事件处理程序的数量与页面整体性能直接相关。每个函数都是对象,都占用内存空间,对象越多,性能越差。为指定事件处理程序所需访问 DOM 的次数会造成整个页面交互的延迟。使用事件委托可以减少内存的消耗和DOM操作,提高性能,节省花在设置页面事件处理程序上的时间。指定一个事件处理程序可以节省 DOM 引用,也可以节省时间。
注意:事件委托是基于事件冒泡的基础上实现的,若事件不支持冒泡则无法实现委托,常见不支持冒泡的事件如下:
- 焦点事件:focus、blur
- 鼠标事件: mouseenter、mouseleave
- UI事件:load、unload、scroll、resize
7、undefined和null的区别是什么?
undefined
表示一个变量已声明但未初始化,或者不存在该变量。null
表示一个变量已经定义,但值为null
。另外,在 JavaScript
中 undefined
是一个全局变量,而 null
是一个关键字。
8、箭头函数的特点?
- 不需要
function
关键字来创建函数 - 省略
return
关键字 - 改变
this
指向
9、简单介绍下原型和原型链
- 原型(
Prototype
):每个 JavaScript 对象都有一个原型(prototype
)属性,该属性指向另一个对象,称为原型对象。原型对象本身也有一个原型,通过这种方式形成了原型链。原型对象可以包含共享的属性和方法,在对象需要访问或调用这些属性和方法时,会沿着原型链进行查找。 - 原型链(
Prototype Chain
):原型链指的是通过原型对象的引用关系,将对象连接起来形成的链表结构。当访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript
引擎会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的末端(null
)
10、简单介绍下Promise
Promise
是 es6
引入异步编程新解决方案,语法上 Promise
是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
Promise构建出来的实例存在以下方法: then()
是实例状态发生改变时的回调函数,第一个参数是resolved
状态的回调函数,第二个参数是 rejected
状态的回调函数 catch() 用于指定发生错误时的回调函数 finally()
用于指定不管 Promise
对象最后状态如何,都会执行的操作,Promise
有三种状态:pending(进行中),fulfilled(已成功),reject(已失败)
。
11、Localstorage、SessionStorage、cookie有什么区别?
一、Cookie
- 存储量太小,只有
4kb
- 所有
http
请求都带着,会影响获取资源的效率 api
简单,需要封装才能用document.cookie
- 本身用于客户端和服务端通信
二、localStorage、sesseionStorage
- 为存储而设计,最大容量
5M
ios safari
隐藏模式下:localStorage.getItem
会报错,建议统一使用try-catch
封装- api简单易用
sessionStorage
用于本地存储一个会话(session
)中的数据,只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁locaStorage
是一个持久化的存储,除非主动删除数据,否则数据是永远不会过期的。
12、什么是模块化? 如何在 JavaScript 中使用模块化?
模块化是指将代码分解为独立的模块,并通过导出和导入来组合这些模块的过程。JavaScript
中的模块化可以使用 CommonJS、AMD
或 ES6
模块等规范来实现。
13、==和===有什么不同?
- 比较的是值:
string == number || boolean || number ....
都会隐式转,换 通过valueOf
转换(valueOf()
方法通常由JavaScript
在后台自动调用,并不显式地出现在代码中。) - === : 除了比较值,还比较类型