目录
null 和 undefined 的区别,如何让一个属性变为null
let、const、var的区别
var ——ES5 变量声明方式
- 在变量未赋值时,变量undefined(为使用声明变量时也为undefined)
- 作用域:var的作用域为方法作用域;只要在方法内定义了,整个方法内的定义变量后的代码都可以使用,可以跨块访问,不能跨函数访问
- var可重复声明变量
let——ES6变量声明方式
- 在变量为声明前直接使用会报错
- 作用域:let为块作用域,通常let比var 范围要小,只能在块作用域里访问,不能跨块访问,也不能跨函数访问
- let禁止重复声明变量,否则会报错
const——ES6变量声明方式
- const为常量声明方式;声明变量时必须初始化,在后面出现的代码中不能再修改该常量的值
- const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动
- 只能在块作用域里访问
作用域的理解
1、定义:作用域就是一个独立的地盘,让变量不会外泄、暴露出去。也就是说作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
2、ES6 之前 JavaScript 没有块级作用域,只有全局作用域和函数作用域。ES6 的到来,为我们提供了‘块级作用域’,可通过新增命令 let 和 const 来体现。
js数据类型及区别
基本数据类型 | Number | |
String | ||
Boolean | ||
null | ||
undefined | ||
symbol(ES6新增) | ||
bigint(ES6新增) | ||
引用数据类型 | object | 普通对象,数组对象,正则对象,日期对象,Math数学函数对象 |
function |
基本数据类型 | 直接存储在栈中的简单数据段,占据空间小、大小固定,属于被频繁使用的数据。栈是存储基本类型值和执行代码的空间 |
引用数据类型 | 存储在堆内存中,占据空间大、大小不固定。引用数据类型在栈中存储了指针,该指针指向堆 中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体 |
区别 |
|
JavaScript判断变量的类型的方法
-
使用typeof检测当需要判断变量是否是number, string, boolean, function, undefined等类型时,可以使用typeof进行判断。
-
使用instanceof检测instanceof运算符与typeof运算符相似,用于识别正在处理的对象的类型。与typeof方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。
-
使用constructor检测constructor本来是原型对象上的属性,指向构造函数。但是根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的。
Object.assign的理解
作用:Object.assign可以实现对象的合并。
语法:Object.assign(target, ...sources)
- Object.assign会将source里面的可枚举属性复制到target,如果和target的已有属性重名,则会覆盖。
- 后续的source会覆盖前面的source的同名属性。
- Object.assign复制的是属性值,如果属性值是一个引用类型,那么复制的其实是引用地址,就会存在引用共享的问题。
constructor的理解
创建的每个函数都有一个prototype(原型)对象,这个属性是一个指针,指向一个对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(继承自构造函数的prototype),指向构造函数的原型对象。注意当将构造函数的prototype设置为等于一个以对象字面量形式创建的新对象时,constructor属性不再指向该构造函数。
map 和 forEach 的异同
相同点 |
|
不同点 |
|
HashMap 和 Array 的区别
查找效率 | HashMap因为其根据hashcode的值直接算出index,所以其查找效率是随着数组长度增大而增加的。 ArrayMap使用的是二分法查找,所以当数组长度每增加一倍时,就需要多进行一次判断,效率下降 |
扩容数量 | HashMap初始值16个长度,每次扩容的时候,直接申请双倍的数组空间。 ArrayMap每次扩容的时候,如果size长度大于8时申请size*1.5个长度,大于4小于8时申请8个,小于4时申 请4个。这样比较ArrayMap其实是申请了更少的内存空间,但是扩容的频率会更高。因此,如果数据量比较大的时候,还是使用HashMap更合适,因为其扩容的次数要比ArrayMap少很多。 |
扩容效率 | HashMap每次扩容的时候重新计算每个数组成员的位置,然后放到新的位置。 ArrayMap则是直接使用System.arraycopy,所以效率上肯定是ArrayMap更占优势。 |
内存消耗 | 以ArrayMap采用了一种独特的方式,能够重复的利用因为数据扩容而遗留下来的数组空间,方便下一个ArrayMap的使用。而HashMap没有这种设计。 由于ArrayMap之缓存了长度是4和8的时候,所以如果频繁的使用到Map,而且数据量都比较小的时候,ArrayMap无疑是相当的是节省内存的。 |
数据量比较小,并且需要频繁的使用Map存储数据的时候,推荐使用ArrayMap。 而数据量比较大的 时候,则推荐使用HashMap。 |
HashMap和Object的区别
相同点:都允许你按键存取一个值、删除键、检测一个键是否绑定了值
不同点:
Set、Map、WeakSet 和 WeakMap 的区别
Set |
|
WeakSet |
|
Map |
|
WeakMap |
|
for of 可以遍历哪些对象
for...of...是es6新增的一个遍历方法,但只限于迭代器(iterator), 所以普通的对象用for...of遍历
是会报错的。
可迭代的对象:包括Array, Map, Set, String, TypedArray, arguments对象等等
js静态类型检查
1、js是动态类型语言
静态类型语言:类型检查发生在编译阶段,因此除非修复错误,否则会一直编译失败
动态类型语言:只有在程序运行了一次的时候错误才会被发现,也就是在运行时,因此即使代码中包含了会在运行时阻止脚本正常运行的错误类型,这段代码也可以通过编译
2、js静态类型检查的方法
(1)Flow是Facebook开发和发布的一个开源的静态类型检查库,它允许你逐渐地向JavaScript代码中添加类型。
(2)TypeScript是一个会编译为JavaScript的超集(尽管它看起来几乎像一种新的静态类型语言)
3、使用静态类型的优势
- 可以尽早发现bug和错误
- 减少了复杂的错误处理
- 将数据和行为分离
- 减少单元测试的数量
- 提供了领域建模(domain modeling)工具
- 帮助我们消除了一整类bug
- 重构时更有信心
4、使用静态类型的劣势
- 代码冗长
- 需要花时间去掌握类型
indexof的理解
数组查找
1、语法:arr.indexOf(searchElement[, fromIndex])
2、参数:
(1)searchElement:需要查招的元素
(2)fromIndex:开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找,-2表示从倒数第二个元素开始查找 ,以此类推。 注意:如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0.
3、返回值:首个被找到的索引位置,如果找不到则返回-1
字符串查找
1、语法:str.indexOf(searchValue [, fromIndex])
2、参数:
(1)searchValue:要被查找的字符串值。
如果没有提供确切地提供字符串,searchValue 会被强制设置为 "undefined"
, 然后在当前字符串中查 找这个值。
举例:'undefined'.indexOf()
将会返回0,因为 undefined
在位置0处被找到,但是 'undefine'.indexOf()
将会返回 -1 ,因为字符串 'undefined'
未被找到。数字表示开始查找的位置。可以是任意整数,默认值为 0
。
(2)fromIndex:可选。如果 fromIndex
的值小于 0
,或者大于 str.length
,那么查找分别从 0
和str.length
开始。(fromIndex
的值小于 0
,等同于为空情况; fromIndex
的值大于或等于 str.length
,那么结果 会直接返回 -1
。)
举例:'hello world'.indexOf('o', -5)
返回 4
,因为它是从位置0和倒数第5个
处开始查找,然后 o
在位置 4
处被找到。另一方面,'hello world'.indexOf('o', 11)
(或 fromIndex
填入任何大于11
的值) 将会返回 -1
,因为开始查找的位置11
处,已经是这个字符串的结尾了。
3、返回值:
(1)查找的字符串 searchValue
的第一次出现的索引,如果没有找到,则返回 -1
。
(2)若被查找的字符串 searchValue
是一个空字符串,则返回fromIndex。如果 fromIndex
值为空,或者 fromIndex
值小于被查找的字符串的长度,返回值即 fromIndex
值。
(3)如果 fromIndex
值大于等于字符串的长度,将会直接返回字符串的长度(str.length
)
4、特点:(1)严格区分大小写;(2)在使用indexOf检索数组时,用‘===’去匹配,意味着会检查数据类型
instanceOf 的理解
1、作用:判断一个实例是否属于某种类型,例子如下:
2、原理 :
3、js的原型继承原理:每个 JavaScript 对象均有一个隐式的 proto 原型属性,而显式的原型属性是 prototype,只有 Object.prototype.proto 属性在未修改的情况下为 null 值
4、手动实现instanceOf(以后补上附链接)
iframe的优点、缺点
优点:
- iframe能够原封不动的把嵌入的网页展现出来。
- 如果有多个网页引用iframe,那么你只需要修改iframe的内容,就可以实现调用的每一个页面内容的更改,方便快捷。
- 网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用iframe来嵌套,可以增加代码的可重用。
- 如果遇到加载缓慢的第三方内容如图标和广告,这些问题可以由iframe来解决。
缺点:
- iframe会阻塞主页面的onload事件;
- iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。会产生很多页面,不容易管理。
- iframe框架结构有时会让人感到迷惑,如果框架个数多的话,可能会出现上下、左右滚动条,会分散访问者的注意力,用户体验度差。
- 代码复杂,无法被一些搜索引擎索引到,这一点很关键,现在的搜索引擎爬虫还不能很好的处理iframe中的内容,所以使用iframe会不利于搜索引擎优化(SEO)。
- 很多的移动设备无法完全显示框架,设备兼容性差。
- iframe框架页面会增加服务器的http请求,对于大型网站是不可取的。
webComponents的理解
Web Components 总的来说是提供一整套完善的封装机制来把 Web 组件化这个东西标准化,每个框架实现的组件都统一标准地进行输入输出,这样可以更好推动组件的复用
包含四个部分:1. Custom Elements,2. HTML Imports,3. HTML Templates,4. Shadow DOM
Custom Elements:提供一种方式让开发者可以自定义 HTML 元素,包括特定的组成,样式和行为。支持 Web Components 标准的浏览器会提供一系列 API 给开发者用于创建自定义的元素,或者扩展现有元素。
HTML Imports:一种在 HTMLs 中引用以及复用其他的 HTML 文档的方式。这个 Import 很漂亮,可以简单理解为我们常见 的模板中的 include
之类的作用
HTML Templates:模板
Shadow DOM:提供一种更好地组织页面元素的方式,来为日趋复杂的页面应用提供强大支持,避免代码间的相互影响
变量提升
JavaScript是单线程语言,所以执行肯定是按顺序执行。但是并不是逐行的分析和执行,而是一段一段地分析执行,会先进行编译阶段然后才是执行阶段。在编译阶段阶段,代码真正执行前的几毫秒,会检测到所有的变量和函数声明,所有这些函数和变量声明都被添加到名为Lexical Environment的JavaScript数据结构内的内存中。所以这些变量和函数能在它们真正被声明之前使用。
arguments的理解
1、定义:在js中,我们在调用有参数的函数时,当往这个调用的有参函数传参时,js会把所传的参数全部存到一个叫arguments的对象里面。它是一个类数组数据。类数组是指在写法上跟数组一样,但是类数组的原型是个对象,类数组不能使用数组的方式。
2、作用:有了arguments这个对象之后,我们可以不用给函数预先设定形参了,可以动态地通过arguments为函数加入参数。
3、常见用法:(1)arguments对象:函数对象内,自动创建的专门接收所有参数值得类数组对象。(2)arguments[i]: 获得传入的下标为i的参数值。(3)arguments.length: 获得传入的参数个数!
3、由来:Javascrip中每个函数都会有一个Arguments对象实例arguments,引用着函数的实参。它是寄生在js函数当中的,不能显式创建,arguments对象只有函数开始时才可用
数组和伪数组(类数组)的区别
1、定义
- 数组是一个特殊对象,与常规对象的区别:
- 当由新元素添加到列表中时,自动更新length属性
- 设置length属性,可以截断数组
- 从Array.protoype中继承了方法
- 属性为'Array'
- 类数组是一个拥有length属性,并且他属性为非负整数的普通对象,类数组不能直接调用数组方法。
2、区别:类数组是简单对象,它的原型关系与数组不同。
3、类数组转换为数组
(1)转换方法
- 使用
Array.from()
- 使用
Array.prototype.slice.call(),会产生稀疏矩阵
- 使用
Array.prototype.forEach()
进行属性遍历并组成新的数组
(2)转换须知
仅考虑 0或正整数 的索引
转换后的数组长度由 length
属性决定。索引不连续时转换结果是连续的,会自动补位。
使用数组方法操作类数组注意地方
数组去重
1. 利用ES6 Set去重(ES6中最常用):不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方***添加去掉重复“{}”的方法。
2. 利用for嵌套for,然后splice去重(ES5中最常用):双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。
3. 利用indexOf去重:新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。
4. 利用sort():利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。
5. 利用对象的属性不能相同的特点进行去重(这种数组去重的方法有问题,不建议用,有待改进)
6. 利用includes
7. 利用hasOwnProperty:利用hasOwnProperty 判断是否存在对象属性
8. 利用filter
9. 利用递归去重
10. 利用Map数据结构去重:创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。
11. 利用reduce+includes
12. [...new Set(arr)]
null 和 undefined 的区别,如何让一个属性变为null
undefined 表示一个变量自然的、最原始的状态值,而 null 则表示一个变量被人为的设置为空对象,而不是原始状态。所以,在实际使用过程中,为了保证变量所代表的语义,不要对一个变量显式的赋值 undefined,当需要释放一个对象时,直接赋值为 null 即可。
undefined 的字面意思就是:未定义的值 。这个值的语义是,希望表示一个变量最原始的状态,而非人为操作的结果 。 这种原始状态会在以下 4 种场景中出现:
-
声明了一个变量,但没有赋值
-
访问对象上不存在的属性
-
函数定义了形参,但没有传递实参
-
使用 void 对表达式求值
因此,undefined 一般都来自于某个表达式最原始的状态值,不是人为操作的结果。当然,你也可以手动给一个变量赋值 undefined,但这样做没有意义,因为一个变量不赋值就是 undefined 。
null 的字面意思是:空值 。这个值的语义是,希望表示 一个对象被人为的重置为空对象,而非一个变量最原始的状态 。 在内存里的表示就是,栈中的变量没有指向堆中的内存对象
null 有属于自己的类型 Null,而不属于Object类型,typeof 之所以会判定为 Object 类型,是因为JavaScript 数据类型在底层都是以二进制的形式表示的,二进制的前三位为 0 会被 typeof 判断为对象类型,而 null 的二进制位恰好都是 0 ,因此,null 被误判断为 Object 类型。
js 中有哪几种内存泄露的情况
- 意外的全局变量;
- 闭包;
- 未被清空的定时器;
- 未被销毁的事件监听;
- DOM 引用;
delete的理解
- delete使用原则:delete 操作符用来删除一个对象的属性。
- delete在删除一个不可配置的属性时在严格模式和非严格模式下的区别:(1)在严格模式中,如果属性是一个不可配置(non-configurable)属性,删除时会抛出异常;(2)非严格模式下返回 false。
- delete能删除的:(1)可配置对象的属性(2)隐式声明的全局变量,全局变量其实是global对象(window)的属性 (3)用户定义的属性 (4)在ECMAScript 6中,通过 const 或 let 声明指定的 "temporal dead zone" (TDZ) 对 delete 操作符也会起作用
- delete不能删除的:(1)显式声明的全局变量 (2)内置对象的内置属性 (3)一个对象从原型继承而来的属性
- delete删除数组元素:(1)当你删除一个数组元素时,数组的 length 属性并不会变小,数组元素变成undefined;(2)当用 delete 操作符删除一个数组元素时,被删除的元素已经完全不属于该数组;(3)如果你想让一个数组元素的值变为 undefined 而不是删除它,可以使用 undefined 给其赋值而不是使用 delete 操作符。此时数组元素是在数组中的
- delete 操作符与直接释放内存(只能通过解除引用来间接释放)没有关系。
继承的优缺点
- 继承的优点
- a:提高了代码的复用性
- b:提高了代码的维护性
- c:让类与类之间产生了关系,是多态的前提
- 继承的缺点
- 类的耦合性增强了,但是开发的原则:高内聚,低耦合。
js继承的方法和相应优缺点
new会发生什么
-
创建空对象;
var obj = {}; -
设置新对象的constructor属性为构造函数的名称,设置新对象的proto属性指向构造函数的prototype对象;
obj.proto = ClassA.prototype;
扩展了新对象的原型链。 -
使用新对象调用函数,函数中的this被指向新实例对象:
ClassA.call(obj); //{}.构造函数(); -
返回this指针。当存在显示的返回时,返回return后面的内容。新建的空对象作废。
面向对象的三个特征的理解
1、概念:
- 封装:将对象运行所需的资源封装在程序对象中——基本上,是方法和数据。对象是“公布其接口”。其他附加到这些接口上的对象不需要关心对象实现的方法即可使用这个对象。这个概念就是“不要告诉我你是怎么做的,只要做就可以了。”对象可以看作是一个自我包含的原子。对象接口包括了公共的方法和初始化数据。
- 继承: 继承可以解决代码复用,让编程更加靠近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过继承父类中的属性和方法。
- 多态: 多态是指一个引用(类型)在不同情况下的多种状态。也可以理解成:多态是指通过指向父类的引用,来调用在不同子类中实现的方法。
2、特点:
- 封装可以隐藏实现细节,使得代码模块化;
- 继承可以扩展已存在的代码模块(类),它们的目的都是为了——代码重用。
- 多态就是相同的事物,调用其相同的方法,参数也相同时,但表现的行为却不同。多态分为两种,一种是行为多态与对象的多态
死锁的理解
1、概念:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源而造成阻塞的现象,若无外力作用,它们都将无法继续执行
2、产生原因
- 竞争资源引起进程死锁
- 可剥夺和非剥夺资源
- 竞争非剥夺资源
- 竞争临时性资源
- 进程推进顺序不当
3、产生条件
- 互斥条件:涉及的资源是非共享的
- 涉及的资源是非共享的,一段时间内某资源只由一个进程占用,如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放
- 不剥夺条件:不能强行剥夺进程拥有的资源
- 进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放
- 请求和保持条件:进程在等待一新资源时继续占有已分配的资源
- 指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放 环路等待条件:存在一种进程的循环链,链中的每一个进程已获得的资源同时被链中的下一个进程所请求 在发生死锁时,必然存在一个进程——资源的环形链
5、检测工具:Jstack命令,JConsole工具
暂时性死区
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
<扩展>
1、let 、const与暂时性死区
2、typeof
与暂时性死区
js中两个数组怎么取交集+(差集、并集、补集)
json和xml数据的区别
- 数据体积方面:xml是重量级的,json是轻量级的,传递的速度更快些。
- 数据传输方面:xml在传输过程中比较占带宽,json占带宽少,易于压缩。
- 数据交互方面:json与javascript的交互更加方便,更容易解析处理,更好的进行数据交互
- 数据描述方面:json对数据的描述性比xml较差
- xml和json都用在项目交互下,xml多用于做配置文件,json用于数据交互。
编码和字符集的区别
字符集是书写系统字母与符号的集合,而字符编码则是将字符映射为一特定的字节或字节序列,是一种规则。通常特定的字符集采用特定的编码方式(即一种字符集对应一种字符编码(例如:ASCII、IOS-8859-1、GB2312、GBK,都是即表示了字符集又表示了对应的字符编码,但Unicode不是,它采用现代的模型))
扩展:
字符:在计算机和电信技术中,一个字符是一个单位的字形、类字形单位或符号的基本信息。即一个字符可以是一个中文汉字、一个英文字母、一个阿拉伯数字、一个标点符号等。
字符集:多个字符的集合。例如GB2312是中国国家标准的简体中文字符集,GB2312收录简化汉字(6763个)及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 个图形字符。
字符编码:把字符集中的字符编码为(映射)指定集合中的某一对象(例如:比特模式、自然数序列、电脉冲),以便文本在计算机中存储和通过通信网络的传递。