前端零散知识点汇总

Q:Node类型简介?

DOM1标准定义Node接口,JavaScript实现了Node类型,JavaScript中所有的节点都继承自Node类型,因此所有节点都共享着相同的基本属性和方法。

Q:Node类型的节点属性有哪些?

  1. nodeType:节点类型,用12个数值常量表示
  2. nodeName/nodeValue:这两个属性的值完全取决于节点的类型,在使用这两个值之前,最好是先检测下节点的类型

Q:Node类型的节点关系有哪些?

  1. childNode:每个节点都有ChildNode属性,保存着一个NodeList对象,NodeList是个类数组对象,用于保存一组有序的节点,DOM结构的变化能够自动反映到NodeList对象中
  2. parentNode
  3. ownerDocument:指向表示整个文档的文档节点
  4. previousSibling/nextSibling
  5. firstChild/lastChild

Q:Node类型有哪些操作节点的方法?

  1. appendChild
  2. insertBefore
  3. replaceChild
  4. removeChild
  5. cloneNode:受一个布尔值,true时表示深复制,复制节点及其整个子节点树,false时表示浅复制,只复制节点本身

Q:常见的Document类型的子节点有哪些?

  1. html:获取方式有 document.documentElement、document.firstChild、document.childNodes[0]
  2. body:获取方式有 document.body

Q:Document类型的文档信息有哪些?

  1. title:取得/修改当前页面的标题并反映在浏览器的标题栏中
  2. URL:只读,包含页面完整的URL
  3. domain:只包含页面的域名,当页面中包含其他子域的框架或者内嵌框架时,通过设置每个页面的document.domain为相同的值,这些页面就可以互相访问对方包含的JavaScript对象了
  4. referrer:只读,保存着链接到当前页面的那个页面的URL,如果没有源页面则是空字符串。

Q:什么是DocumentFragment以及如何创建?

文档片段,轻量级的文档,可以包含和控制节点,但不会像完整文档那样占用额外的资源。
可以把文档片段理解为仓库,立马保存将来可能会添加到文档中的节点。

创建:document.createDocumentFragment()

Q:DOM扩展了那些选择API?

  1. querySelector方法:返回与该模式匹配的第一个元素,如没找到返回null
  2. querySelectorAll方法:返回的是所有匹配匹配的元素,注意返回的其实是NodeList的快照
  3. matchesSelector方法:如果调用元素与该选择符匹配,返回true。使用这个方法能够方便地检测它是否会被querySelector或querySelectorAll返回

Q:HTML5增加了哪些与类相关的扩充?

  1. getElementByClassName方法
  2. classList属性
    • add方法:将给定的字符串值添加到列表中,如果值存在,则不添加
    • contains方法:列表中是否存在给定的值,如果存在则返回true,否则返回false
    • remove方法:从列表中删除给定的字符串
    • toggle方法:如果列表中已经存在给定的值,删除它,如果列表中没有给定的值,添加它

Q:HTML5对焦点管理提供了哪些扩展?

  1. document.activeElement:始终引用DOM中当前获得了焦点的元素,元素获得焦点的方式有页面加载,用户输入,代码中调用focus方法(注意:默认情况下,文档刚刚加载完成时,document.activeElement中保存的是document.body元素。文档加载期间,值为null)
  2. document.hasFocus:用来确认文档是否获得了焦点

Q:说说你对闭包的理解?

使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
闭包有三个特性:
1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收

Q:请你谈谈Cookie的弊端?

  1. Cookie数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。
  2. 安全性问题。

Q:简介浏览器本地存储?

html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage。

  1. sessionStorage:会话期间有效
  2. localStorage:用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。
  3. localStorage和sessionStorage都具有相同的操作方法,例如setItem、getItem和removeItem等

Q:web storage和cookie的区别

  1. Cookie是不可或缺的,作为HTTP规范的一部分存在,用于与服务器的交互,Cookie本身存在一些局限性,比如大小受限,受同源策略限制等。没有兼容性问题
  2. Web Storage是为了本地“存储”数据而生,没有Cookie使用时的限制,还拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。IE7以上浏览器支持。

Q:cookie 和session 的区别?

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上。
  2. cookie有安全问题、大小跟数量的限制
  3. session过多会影响服务器性能。

所以,重要信息存放为SESSION,其他信息如果需要保留,可以放在COOKIE中

Q:display:none和visibility:hidden的区别?

display:none 隐藏对应的元素,不占据文档空间。
visibility:hidden 隐藏对应的元素,占据文档空间。

Q:CSS中 link 和@import 的区别是?

  1. link属于HTML标签,而@import是CSS提供的;
  2. 页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
  3. import只在IE5以上才能识别,而link是HTML标签,无兼容问题;
  4. link方式的样式的权重 高于@import的权重.

Q:CSS3新增伪类有那些?

伪类 注明
p:last-of-type 选择其父元素的最后的一个P元素
p:last-child 选择其父元素的最后子元素(一定是P才行)
p:first-of-type 选择其父元素的首个P元素
p:first-child 选择其父元素的首个p元素(一定是p才行)
p:only-child 选择其父元素的只有一个元素(而且这个元素只能是p元素,不能有其他元素)
p:only-of-type 选择其父元素的只有一个p元素(不能有第二个P元素,其他元素可以有) 
p:nth-child(n) 选择其父元素的第N个 刚好是p的元素
p:nth-last-child(n) 从最后一个子元素开始计数
p:nth-of-type(n) 选择其父元素的n个元素
p:nth-last-of-type(n) 从最后一个子元素开始计数
:enabled 用在input上,选择被禁用的表单元素

Q:position有哪些属性,分别是相对于谁进行定位的?

  1. absolute:生成绝对定位的元素, 相对于最近一级定位不是 static的父元素来进行定位。
  2. fixed:生成绝对定位的元素,相对于浏览器窗口进行定位。
  3. relative:生成相对定位的元素,相对于其在普通流中的位置进行定位。
  4. static:默认值。没有定位,元素出现在正常的流中

Q:CSS3有哪些新特性?

  1. CSS3实现圆角(border-radius)
  2. 阴影(box-shadow)
  3. 对文字加特效(text-shadow、)
  4. 线性渐变(gradient)
  5. CSS3动画
  6. 媒体查询
  7. 多栏布局

Q:XML和JSON的区别?

JSON相比XML的优势:数据体积小、传输速度快,更容易被解析
XML相比JSON的优势:XML对数据的描述更强

Q:说说你对语义化的理解?

  1. 去掉或者丢失样式的时候能够让页面呈现出清晰的结构
  2. 有利于SEO
  3. 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)
  4. 便于团队开发和维护,语义化更具可读性

Q:清除浮动的几种方法:

1.额外标签法,< div style=”clear:both;”></ div>
2,使用after伪类

1
2
3
4
5
6
7
#parent:after{
content:".";
height:0;
visibility:hidden;
display:block;
clear:both;
}

  1. 使用BFC清除浮动

Q:html5有哪些新特性?

  1. 拖拽释放(Drag and drop) API
  2. 语义化更好的内容标签(header,nav,footer,aside,article,section)
  3. 音频、视频API(audio,video)
  4. 画布(Canvas) API
  5. 地理(Geolocation) API
  6. WebStore: localStorage、sessionStorage

Q:如何实现浏览器内多个标签页之间的通信?

localstorge、cookies

Q:什么是 “use strict”; ? 使用它的好处?

“严格模式”

  1. 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
  2. 消除代码运行的一些不安全之处,保证代码运行的安全;
  3. 提高编译器效率,增加运行速度;
  4. 为未来新版本的Javascript做好铺垫。

注:IE6,7,8,9均不支持严格模式。

Q:一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?

  1. 首先,在浏览器地址栏中输入url
  2. 浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
  3. 在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。
  4. 浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。
  5. 握手成功后,浏览器向服务器发送http请求,请求数据包。
  6. 服务器处理收到的请求,将数据返回至浏览器
  7. 浏览器收到HTTP响应
  8. 读取页面内容,浏览器渲染,解析html源码
  9. 生成Dom树,解析css样式,js交互

Q:JS的组成是?

  1. 核心语法
    • 基本的语法构造(比如操作符、控制结构、语句)
    • 标准库(就是一系列具有各种功能的对象比如Array、Date、Math等)
  2. 宿主环境提供额外的 API

Q:浏览器为JS提供了哪些额外的API?

  1. 浏览器控制类:操作浏览器
  2. DOM 类:操作网页的各种元素
  3. Web 类:实现互联网的各种功能

Q:JS的复杂性体现在哪?

  1. 涉及大量的外部 API
  2. 设计缺陷。

Q:Object对象提供了哪些跟对象属性模型相关的静态方法?

  1. Object.keys():返回直接定义在某个对象上面的全部属性的名称(不包含不可枚举的属性)
  2. Object.getOwnPropertyNames():返回直接定义在某个对象上面的全部属性的名称(包含不可枚举的属性)
  3. Object.getOwnPropertyDescriptor():获取某个属性的attributes对象。
  4. Object.defineProperty():通过attributes对象,定义某个属性。
  5. Object.defineProperties():通过attributes对象,定义多个属性。

Q:Object对象提供了哪些跟控制对象状态相关的静态方法?

  1. Object.preventExtensions():阻止向对象添加新属性。
  2. Object.isExtensible():判断是否可向对象添加新属性
  3. Object.seal():阻止修改现有属性的特性,并阻止添加新属性
  4. Object.isSealed():如果无法在对象中修改现有属性的特性,且无法向对象添加新属性,则返回 true
  5. Object.freeze():阻止修改现有属性的特性和值,并阻止添加新属性。
  6. Object.isFrozen():如果无法在对象中修改现有属性的特性和值,且无法向对象添加新属性,则返回 true。

Q:Object对象提供了哪些跟原型链相关的静态方法?

  1. Object.create():该方法可以指定原型对象和属性,返回一个新的对象。
  2. Object.getPrototypeOf():获取对象的Prototype对象。

Q:Object对象的实例方法

  1. valueOf():返回当前对象对应的值。avaScript自动类型转换时会默认调用这个方法
  2. toString():返回当前对象对应的字符串形式。
  3. toLocaleString():返回当前对象对应的本地字符串形式。
  4. hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
  5. isPrototypeOf():判断当前对象是否为另一个对象的原型。prototype.isPrototypeOf(object)

Q:如何确定一个值的类型?

  1. typeof运算符
  2. instanceof运算符
  3. Object.prototype.toString方法

Q:NaN出现的场景有哪些?

  1. 字符串解析成数字出错
  2. 一些数学函数的运算结果会出现NaN
  3. 0除以0也会得到NaN

Q:NaN的运算规则是?

  1. NaN不等于任何值,包括它本身
  2. NaN与任何数(包括它自己)的运算,得到的都是NaN

Q:判断NaN的方法是?

  1. isNaN(注意:只对数值有效,如果传入其他值,会被先转成数值。使用isNaN之前,最好判断一下数据类型)
  2. 利用NaN不等于自身进行判断。

Q:与数值相关的全局方法有哪些?

  1. parseInt():用于将字符串转为整数(返回值只有两种可能,十进制整数或者NaN)
  2. parseFloat():用于将一个字符串转为浮点数

Q:Array实例的方法有哪些?

  1. valueOf():返回数组本身。
  2. toString():返回数组的字符串形式。
  3. push():在数组的末端添加元素
  4. pop():删除数组的最后一个元素
  5. shift():删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组。
  6. unshift():在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
  7. join():以参数作为分隔符,将所有数组成员组成一个字符串返回
  8. concat():用于多个数组的合并,返回一个新数组,原数组不变。
  9. reverse():颠倒数组中元素的顺序,返回改变后的数组。注意,该方法将改变原数组。
  10. slice():提取原数组的一部分,返回一个新数组,原数组不变。
    • 它的第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素本身不包括在内)。如果省略第二个参数,则一直返回到原数组的最后一个成员。
    • slice没有参数,实际上等于返回一个原数组的拷贝
    • slice方法的参数是负数,则表示倒数计算的位置
  11. splice():用于删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。
    • 第一个参数是删除的起始位置,第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素
  12. sort():对数组成员进行排序
  13. map():对数组的所有成员依次调用一个函数,根据函数结果返回一个新数组。
  14. forEach():与map方法很相似,但是forEach方法一般不返回值,只用来操作数据。如果需要有返回值,一般使用map方法。
  15. filter():参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。
  16. some()、every():接受一个函数作为参数,所有数组成员依次执行该函数,返回一个布尔值
    • some,只要有一个数组成员的返回值是true,则整个some方法的返回值就是true,否则false。
    • every,所有数组成员的返回值都是true,才返回true,否则false。
  17. reduce()、reduceRight():依次处理数组的每个成员,最终累计为一个值。reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样。
  18. indexOf(),lastIndexOf():indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。lastIndexOf方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1。

Q:什么是包装对象?

通过Number、String、Boolean这三个原生对象可以把原始类型的值包装成对象,使得原始类型的值也可以调用对象方法

Q:包装对象实例的方法有哪些?

  1. valueOf():返回包装对象实例对应的原始类型的值
  2. toString():返回实例对应的字符串形式

Q:原始类型如何自动转换?

原始类型的值,可以自动当作对象调用,即调用各种对象的方法和参数。这时,JavaScript引擎会自动将原始类型的值转为包装对象,在使用后立刻销毁。

Q:Number对象实例方法有哪些?

  1. Number.prototype.toString():用来将一个数值转为字符串形式。
  2. Number.prototype.toFixed():将一个数转为指定位数的小数,返回这个小数对应的字符串。

Q:String实例对象的方法有哪些?

  1. charAt方法返回指定位置的字符,参数是从0开始编号的位置。如果参数为负数,或大于等于字符串的长度,charAt返回空字符串。(完全可以用数组下标替代)
  2. charCodeAt):返回给定位置字符的Unicode码点
  3. concat():用于连接两个字符串,返回一个新字符串,不改变原字符串。
  4. slice():用于从原字符串取出子字符串并返回,不改变原字符串。
    • 它的第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。
    • 如果省略第二个参数,则表示子字符串一直到原字符串结束。
    • 如果参数是负值,表示从结尾开始倒数计算的位置,即该负值加上字符串长度。
    • 如果第一个参数大于第二个参数,slice方法返回一个空字符串。
  5. substring():用于从原字符串取出子字符串并返回,不改变原字符串。它与slice作用相同,但有一些奇怪的规则,因此不建议使用这个方法,优先使用slice。
  6. substr():用于从原字符串取出子字符串并返回,不改变原字符串。
    • 第一个参数是子字符串的开始位置,第二个参数是子字符串的长度。
    • 如果省略第二个参数,则表示子字符串一直到原字符串的结束。
    • 如果第一个参数是负数,表示倒数计算的字符位置。如果第二个参数是负数,将被自动转为0,因此会返回空字符串。
  7. indexOf(),lastIndexOf():用于确定一个字符串在另一个字符串中的位置,都返回一个整数,表示匹配开始的位置。如果返回-1,就表示不匹配。两者的区别在于,indexOf从字符串头部开始匹配,lastIndexOf从尾部开始匹配。它们还可以接受第二个参数,对于indexOf方法,第二个参数表示从该位置开始向后匹配;对于lastIndexOf,第二个参数表示从该位置起向前匹配。
  8. trim():用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。
  9. toLowerCase(),toUpperCase():toLowerCase方法用于将一个字符串全部转为小写,toUpperCase则是全部转为大写。它们都返回一个新字符串,不改变原字符串。
  10. match():用于确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串。如果没有找到匹配,则返回null。
  11. search():等同于match,但是返回值为匹配的第一个位置。如果没有找到匹配,则返回-1
  12. replace():用于替换匹配的子字符串,一般情况下只替换第一个匹配(除非使用带有g修饰符的正则表达式)。
  13. split():按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。接受第二个参数,限定返回数组的最大成员数。

Q:常见的Math方法有哪些?

  1. Math.abs():绝对值
  2. Math.ceil():向上取整
  3. Math.floor():向下取整
  4. Math.max():最大值
  5. Math.min():最小值
  6. Math.round():四舍五入
  7. Math.random():随机数

Q:Date对象的静态方法有哪些?

  1. Date.now():返回当前距离1970年1月1日 00:00:00 UTC的毫秒数
  2. Date.parse():用来解析日期字符串,返回距离1970年1月1日 00:00:00的毫秒数。
  3. Date.UTC():默认情况下,Date对象返回的都是当前时区的时间。Date.UTC方法可以返回UTC时间(世界标准时间)。该方法接受年、月、日等变量作为参数,返回当前距离1970年1月1日 00:00:00 UTC的毫秒数。

Q:Date实例对象的get类方法有哪些?

获取Date对象的日期和时间。(返回的都是整数,以下方法都有对应的UTC版本,用来返回UTC时间。)

  1. getTime():返回距离1970年1月1日00:00:00的毫秒数,等同于valueOf方法。
  2. getDate():返回实例对象对应每个月的几号(从1开始)。
  3. getDay():返回星期几,星期日为0,星期一为1,以此类推。
  4. getYear():返回距离1900的年数。
  5. getFullYear():返回四位的年份。
  6. getMonth():返回月份(0表示1月,11表示12月)。
  7. getHours():返回小时(0-23)。
  8. getMilliseconds():返回毫秒(0-999)。
  9. getMinutes():返回分钟(0-59)。
  10. getSeconds():返回秒(0-59)。

Q:Date实例对象的set类方法有哪些?

设置Date对象的日期和时间。(以下方法都有对应的UTC版本)

  1. setDate(date):设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳。
  2. setYear(year): 设置距离1900年的年数。
  3. setFullYear(year [, month, date]):设置四位年份。
  4. setHours(hour [, min, sec, ms]):设置小时(0-23)。
  5. setMilliseconds():设置毫秒(0-999)。
  6. setMinutes(min [, sec, ms]):设置分钟(0-59)。
  7. setMonth(month [, date]):设置月份(0-11)。
  8. setSeconds(sec [, ms]):设置秒(0-59)。
  9. setTime(milliseconds):设置毫秒时间戳。

Q: 正则对象的属性有哪些?

正则对象的属性分成两类。
一类是修饰符相关,返回一个布尔值,表示对应的修饰符是否设置。

  1. ignoreCase:返回一个布尔值,表示是否设置了i修饰符,该属性只读。
  2. global:返回一个布尔值,表示是否设置了g修饰符,该属性只读。
  3. multiline:返回一个布尔值,表示是否设置了m修饰符,该属性只读。

另一类是与修饰符无关的属性,主要是下面两个。

  1. lastIndex:返回下一次开始搜索的位置。该属性可读写,但是只在设置了g修饰符时有意义。
  2. source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。

Q: 正则对象的方法有哪些?

test、exec

理解正则表达式的test方法?

返回一个布尔值,表示当前模式是否能匹配参数字符串。

  1. 如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。
  2. 带有g修饰符时,可以通过正则对象的lastIndex属性指定开始搜索的位置。

理解正则表达式的exec方法?

返回匹配结果。如果发现匹配,就返回一个数组,成员是每一个匹配成功的子字符串,否则返回null。

  1. 如果正则表示式包含圆括号(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。
  2. exec方法的返回数组还包含以下两个属性:
    • input:整个原字符串。
    • index:整个模式匹配成功的开始位置(从0开始计数)
  3. 如果正则表达式加上g修饰符,则可以使用多次exec方法,下一次搜索的位置从上一次匹配成功结束的位置开始。

Q:字符串对象的方法有哪些跟正则对象有关?

  1. match():返回一个数组,成员是所有匹配的子字符串。
  2. search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。
  3. replace():按照给定的正则表达式进行替换,返回替换后的字符串。
  4. split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。

Q:正则表达式中的字面量字符和元字符分别是什么?

  1. 字面量:如果在正则表达式之中,某个字符只表示它字面的含义,那么它们就叫做“字面量字符”
  2. 元字符:除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思。它们叫做元字符

Q:正则表达式中常见的元字符有哪些?

  1. 点字符(.):匹配除回车(\r)、换行(\n) 、行分隔符(\u2028)和段分隔符(\u2029)以外的所有字符。
  2. 位置字符:用来提示字符所处的位置,主要有两个字符。
    • ^ 表示字符串的开始位置
    • $ 表示字符串的结束位置
  3. 选择符(|):在正则表达式中表示“或关系”(OR)

Q:正则表达式中的转义符是什么?

转义符:正则表达式中那些有特殊含义的字符,如果要匹配它们本身,就需要在它们前面要加上反斜杠。一共有12个字符:^、.、[、$、(、)、|、*、+、?、{和\

Q:正则表达式中的字符类是什么?

字符类(class)表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内,比如[xyz] 表示x、y、z之中任选一个匹配。

  1. 脱字符(^):如果方括号内的第一个字符是[^],则表示除了字符类之中的字符,其他字符都可以匹配。
  2. 连字符(-):某些情况下,对于连续序列的字符,连字符(-)用来提供简写形式,表示字符的连续范围。

Q:正则表达式中的预定义模式有什么?

预定义模式指的是某些常见模式的简写方式。

  1. \d 匹配0-9之间的任一数字,相当于[0-9]。
  2. \D 匹配所有0-9以外的字符,相当于[^0-9]。
  3. \w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。
  4. \W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。
  5. \s 匹配空格(包括制表符、空格符、断行符等),相等于[\t\r\n\v\f]。
  6. \S 匹配非空格的字符,相当于[^\t\r\n\v\f]。
  7. \b 匹配词的边界。
  8. \B 匹配非词边界,即在词的内部。

Q:正则表达式的重复类是什么?

模式的精确匹配次数,使用大括号({})表示。{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。

Q:正则表达式的量词符是什么?

量词符用来设定某个模式出现的次数。

  1. ? 问号表示某个模式出现0次或1次,等同于{0, 1}。
    • 星号表示某个模式出现0次或多次,等同于{0,}。
    • 加号表示某个模式出现1次或多次,等同于{1,}。

Q:正则表达式的贪婪模式是什么?

量词符(? * +),默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止。这被称为贪婪模式。
如果想将贪婪模式改为非贪婪模式,可以在量词符后面加一个问号。

  1. *?:表示某个模式出现0次或多次,匹配时采用非贪婪模式。
  2. +?:表示某个模式出现1次或多次,匹配时采用非贪婪模式。

正则表达式的修饰符有哪些?

修饰符(modifier)表示模式的附加规则,放在正则模式的最尾部。
修饰符可以单个使用,也可以多个一起使用。

  1. g修饰符:表示全局匹配(global),加上它以后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。
  2. i修饰符:默认情况下,正则对象区分字母的大小写,加上i修饰符以后表示忽略大小写
  3. m修饰符:m修饰符表示多行模式(multiline),会修改^和$的行为。默认情况下(即不加m修饰符时),^和$匹配字符串的开始处和结尾处,加上m修饰符以后,^和$还会匹配行首和行尾,即^和$会识别换行符(\n)。

Q:正则表达式的组匹配是什么?

正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容。
注意,使用组匹配时,不宜同时使用g修饰符,否则match方法不会捕获分组的内容。

在正则表达式内部,可以用\n引用括号匹配的内容,n是从1开始的自然数,表示对应顺序的括号。

1
/(.)b(.)\1b\2/.test("abcabc") // true

Q:正则表达式中的非捕获组是什么?

(?:x)称为非捕获组(Non-capturing group),表示不返回该组匹配的内容,即匹配的结果中不计入这个括号。

非捕获组的作用请考虑这样一个场景,假定需要匹配foo或者foofoo,正则表达式就应该写成/(foo){1, 2}/,但是这样会占用一个组匹配。这时,就可以使用非捕获组,将正则表达式改为/(?:foo){1, 2}/,它的作用与前一个正则是一样的,但是不会单独输出括号内部的内容。

1
2
3
var m = 'abc'.match(/(?:.)b(.)/);
m // ["abc", "c"]
// 上面代码中的模式,一共使用了两个括号。其中第一个括号是非捕获组,所以最后返回的结果中没有第一个括号,只有第二个括号匹配的内容。

Q:正则表达式中的先行断言是什么?

x(?=y)称为先行断言(Positive look-ahead),x只有在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟着百分号的数字,可以写成/\d+(?=%)/。

“先行断言”中,括号里的部分是不会返回的。

1
2
3
var m = 'abc'.match(/b(?=c)/);
m // ["b"]
// 上面的代码使用了先行断言,b在c前面所以被匹配,但是括号对应的c不会被返回。

Q:正则表达式中的先行否定断言是什么?

x(?!y)称为先行否定断言(Negative look-ahead),x只有不在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟的不是百分号的数字,就要写成/\d+(?!%)/。
“先行否定断言”中,括号里的部分是不会返回的。

1
2
3
4
5
/\d+(?!\.)/.exec('3.14') // ["14"]
// 上面代码中,正则表达式指定,只有不在小数点前面的数字才会被匹配,因此返回的结果就是14。
var m = 'abd'.match(/b(?!c)/);
m // ['b']
// 上面的代码使用了先行否定断言,b不在c前面所以被匹配,而且括号对应的d不会被返回。

Q:JSON.stringify()的用法是?

JSON.stringify():将一个值转为字符串。该字符串符合 JSON 格式,并且可以被JSON.parse方法还原。

  1. 对于原始类型的字符串,转换结果会带双引号。字符串foo,被转成了””foo””
  2. 如果原始对象中,有一个成员的值是undefined、函数或 XML 对象,这个成员会被过滤。
  3. 如果数组的成员是undefined、函数或 XML 对象,则这些值被转成null。
  4. 正则对象会被转成空对象。
  5. JSON.stringify方法会忽略对象的不可遍历属性。

Q:JSON.parse()的用法是?

JSON.parse方法用于将JSON字符串转化成对象。
如果传入的字符串不是有效的JSON格式,JSON.parse方法将报错。
JSON.parse方法可以接受一个处理函数,用法与JSON.stringify方法类似。

Q:属性描述对象是什么?

JavaScript提供了一个内部数据结构,用来描述一个对象的属性的行为,控制它的行为。这被称为“属性描述对象”。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。

  1. value:value存放该属性的属性值,默认为undefined。
  2. writable:存放一个布尔值,表示属性值(value)是否可改变,默认为true。
  3. enumerable:存放一个布尔值,表示该属性是否可枚举,默认为true。如果设为false,会使得某些操作(比如for…in循环、Object.keys())跳过该属性。
  4. configurable:存放一个布尔值,表示“可配置性”,默认为true。如果设为false,将阻止某些操作改写该属性,比如,无法删除该属性,也不得改变该属性的属性描述对象(value属性除外)。也就是说,configurable属性控制了属性描述对象的可写性。
  5. get:存放一个函数,表示该属性的取值函数(getter),默认为undefined。
  6. set:存放一个函数,表示该属性的存值函数(setter),默认为undefined。

Object.getOwnPropertyDescriptor方法可以读出对象自身属性的属性描述对象。

Q:理解Object.defineProperty(),Object.defineProperties()?

Object.defineProperty方法允许通过定义属性描述对象,来定义或修改一个属性,然后返回修改后的对象。它的格式:Object.defineProperty(object, propertyName, attributesObject)

Object.defineProperty方法接受三个参数:

  1. 第一个是属性所在的对象
  2. 第二个是属性名(它应该是一个字符串)
  3. 第三个是属性的描述对象。它的writable、configurable、enumerable这三个属性的默认值都为false。
    • writable属性为false,表示对应的属性的值将不得改写。
    • configurable属性为false,将无法删除该属性,也无法修改attributes对象(value属性除外)。
    • enumerable属性为false,表示对应的属性不会出现在for…in循环和Object.keys方法中。

如果一次性定义或修改多个属性,可以使用Object.defineProperties方法。
需要注意的是,Object.defineProperty方法和Object.defineProperties方法,都有性能损耗,不宜大量使用。

Q:对象的元属性是什么?

属性描述对象的属性,被称为“元属性”,因为它可以看作是控制属性的属性。
一共有三种:可枚举性、可配置性、可写性

Q:元属性中的可枚举性(enumerable)是什么?

如果一个属性的enumerable为false,下面三个操作不会取到该属性。

  1. for..in循环
  2. Object.keys方法
  3. JSON.stringify方法

Q:元属性中的可配置性(configurable)是什么?

决定了是否可以修改属性描述对象。也就是说,当configurable为false的时候,value、writable、enumerable和configurable都不能被修改了。

需要注意的是:

  1. writable只有在从false改为true会报错,从true改为false则是允许的。
  2. 至于value,只要writable和configurable有一个为true,就允许改动。
  3. configurable为false时,直接对该属性赋值,不报错,但不会成功。

Q:元属性中的可写性(writable)是什么?

决定了属性的值(value)是否可以被改变。

Q:理解Object.getOwnPropertyNames()?

Object.getOwnPropertyNames方法返回直接定义在某个对象上面的全部属性的名称,而不管该属性是否可枚举。

Q:理解Object.prototype.propertyIsEnumerable()?

对象实例的propertyIsEnumerable方法用来判断一个属性是否可枚举。

Q:理解存取器(accessor)?

除了直接定义以外,属性还可以用存取器(accessor)定义。其中,存值函数称为setter,使用set命令;取值函数称为getter,使用get命令。

Q:理解对象的拷贝?

有时,我们需要将一个对象的所有属性,拷贝到另一个对象。ES5没有提供这个方法,必须自己实现。

1
2
3
4
5
6
7
8
9
10
11
12
var extend = function (to, from) {
for (var property in from) {
to[property] = from[property];
}
return to;
}
extend({}, {
a: 1
})
// {a: 1}

上面这个方法的问题在于,如果遇到存取器定义的属性,会只拷贝值。

1
2
3
4
extend({}, {
get a() { return 1 }
})
// {a: 1}

为了解决这个问题,我们可以通过Object.defineProperty方法来拷贝属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var extend = function (to, from) {
for (var property in from) {
Object.defineProperty(
to,
property,
Object.getOwnPropertyDescriptor(from, property)
);
}
return to;
}
extend({}, { get a(){ return 1 } })
// { get a(){ return 1 } })

这段代码还是有问题,拷贝某些属性时会失效。

1
2
3
extend(document.body.style, {
backgroundColor: "red"
});

上面代码的目的是,设置document.body.style.backgroundColor属性为red,但是实际上网页的背景色并不会变红。但是,如果用第一种简单拷贝的方法,反而能够达到目的。这提示我们,可以把两种方法结合起来,对于简单属性,就直接拷贝,对于那些通过属性描述对象设置的属性,则使用Object.defineProperty方法拷贝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var extend = function (to, from) {
for (var property in from) {
var descriptor = Object.getOwnPropertyDescriptor(from, property);
if (descriptor && ( !descriptor.writable
|| !descriptor.configurable
|| !descriptor.enumerable
|| descriptor.get
|| descriptor.set)) {
Object.defineProperty(to, property, descriptor);
} else {
to[property] = from[property];
}
}
}

上面的这段代码,可以很好地拷贝对象所有可遍历(enumerable)的属性。

Q:new 命令的原理?

  1. 创建一个空对象,作为将要返回的对象实例
  2. 将这个空对象的原型,指向构造函数的prototype属性
  3. 将这个空对象赋值给函数内部的this关键字
  4. 开始执行构造函数内部的代码

Q:如何判断函数调用的时候,是否使用new命令?

函数内部可以使用new.target属性。如果当前函数是new命令调用,new.target指向当前函数,否则为undefined。

Q:this的使用场景有哪些?

  1. 全局环境:在全局环境使用this,它指的就是顶层对象window
  2. 构造函数:构造函数中的this,指的是实例对象。
  3. 对象的方法:当 A 对象的方法被赋予 B 对象,该方法中的this就从指向 A 对象变成了指向 B 对象。

Q:function.prototype.bind()的理解?

bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。
注意点:

  1. 每一次返回一个新函数
  2. 结合回调函数使用

Q:function.prototype.bind()的作用?

bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。
对于那些不支持bind方法的老式浏览器,可以自行定义bind方法。

1
2
3
4
5
6
7
8
9
10
if(!('bind' in Function.prototype)){
Function.prototype.bind = function(){
var fn = this;
var context = arguments[0];
var args = Array.prototype.slice.call(arguments, 1);
return function(){
return fn.apply(context, args);
}
}
}

注意点:

  1. 每一次返回一个新函数
  2. 结合回调函数使用
1
2
3
4
5
6
7
8
9
10
obj.print = function () {
this.times.forEach(function (n) {
console.log(this.name);
}.bind(this));
};
obj.print()
// 张三
// 张三
// 张三
  1. 结合call方法使用
    利用bind方法,可以改写一些JavaScript原生方法的使用形式,以数组的slice方法为例。
    1
    2
    3
    [1, 2, 3].slice(0, 1)// [1]
    // 等同于
    Array.prototype.slice.call([1, 2, 3], 0, 1)// [1]

上面的代码中,数组的slice方法从[1, 2, 3]里面,按照指定位置和长度切分出另一个数组。这样做的本质是在[1, 2, 3]上面调用Array.prototype.slice方法,因此可以用call方法表达这个过程,得到同样的结果。

call方法实质上是调用Function.prototype.call方法,因此上面的表达式可以用bind方法改写。

1
2
var slice = Function.prototype.call.bind(Array.prototype.slice);
slice([1, 2, 3], 0, 1) // [1]

可以看到,利用bind方法,将[1, 2, 3].slice(0, 1)变成了slice([1, 2, 3], 0, 1)的形式。

如果再进一步,将Function.prototype.call方法绑定到Function.prototype.bind对象,就意味着bind的调用形式也可以被改写。

1
2
3
4
5
6
function f() {
console.log(this.v);
}
var o = { v: 123 };
var bind = Function.prototype.call.bind(Function.prototype.bind);
bind(f, o)() // 123

上面代码表示,将Function.prototype.call方法绑定Function.prototype.bind以后,bind方法的使用形式从f.bind(o),变成了bind(f, o)。

Q:prototype 属性的作用是什么?

JavaScript 的每个对象都继承另一个对象,后者称为“原型”(prototype)对象。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。null也可以充当原型,区别在于它没有自己的原型对象。
JavaScript 继承机制的设计就是,原型的所有属性和方法,都能被子对象共享。

Q:理解原型链?

对象的属性和方法,有可能定义在自身,也有可能定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。
所有对象的原型最终都可以上溯到Object.prototype,而Object.prototype对象就是null,而null对象没有自己的原型。

“原型链”的作用是,读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。

Q:理解constructor 属性?

prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数。
由于constructor属性定义在prototype对象上面,意味着可以被所有实例对象继承。
constructor属性的作用,是分辨原型对象到底属于哪个构造函数。

有了constructor属性,就可以从实例新建另一个实例。

1
2
3
4
5
function Constr() {}
var x = new Constr();
var y = new x.constructor();
y instanceof Constr // true

这使得在实例方法中,调用自身的构造函数成为可能。

1
2
3
Constr.prototype.createCopy = function () {
return new this.constructor();
};

constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。

1
2
3
4
5
6
7
8
9
function Person(name) {
this.name = name;
}
Person.prototype.constructor === Person // true
Person.prototype.copy = function () {
return new this.constructor(this.name);
};

此外,通过name属性,可以从实例得到构造函数的名称。

1
2
3
function Foo() {}
var f = new Foo();
f.constructor.name // "Foo"

Q:理解instanceof 运算符?

instanceof运算符返回一个布尔值,表示某个对象是否为指定的构造函数的实例。

instanceof运算符的左边是实例对象,右边是构造函数。它会检查右边构建函数的原型对象(prototype),是否在左边对象的原型链上。因此,下面两种写法是等价的。

1
2
3
v instanceof Vehicle
// 等同于
Vehicle.prototype.isPrototypeOf(v)

instanceof的原理是检查原型链,对于那些不存在原型链的对象,就无法判断。

1
Object.create(null) instanceof Object // false

除了上面这种继承null的特殊情况,JavaScript 之中,只要是对象,就有对应的构造函数。因此,instanceof运算符的一个用处,是判断值的类型。

1
2
3
4
var x = [1, 2, 3];
var y = {};
x instanceof Array // true
y instanceof Object // true

Q:理解Object.create()?

接受一个对象作为参数,然后以它为原型,返回一个实例对象。该实例完全继承继承原型对象的属性。
如果老式浏览器不支持Object.create方法,可以就用这段代码自己部署。

1
2
3
4
5
6
7
if (typeof Object.create !== 'function') {
Object.create = function (obj) {
function F() {}
F.prototype = obj;
return new F();
};
}

除了对象的原型,Object.create方法还可以接受第二个参数。该参数是一个属性描述对象,它所描述的对象属性,会添加到实例对象,作为该对象自身的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var obj = Object.create({}, {
p1: {
value: 123,
enumerable: true,
configurable: true,
writable: true,
},
p2: {
value: 'abc',
enumerable: true,
configurable: true,
writable: true,
}
});
// 等同于
var obj = Object.create({});
obj.p1 = 123;
obj.p2 = 'abc';

Q;获取原型对象方法的比较?

获取实例对象obj的原型对象,有三种方法。

  1. obj.proto
  2. obj.constructor.prototype
  3. Object.getPrototypeOf(obj)

上面三种方法之中,前两种都不是很可靠。最新的ES6标准规定,proto属性只有浏览器才需要部署,其他环境可以不部署。而obj.constructor.prototype在手动改变原型对象时,可能会失效。
所以,推荐使用第三种Object.getPrototypeOf方法,获取原型对象。

Q:理解Object.getOwnPropertyNames()?

Object.getOwnPropertyNames方法返回一个数组,成员是对象本身的所有属性的键名,不包含继承的属性键名。
只获取那些可以枚举的属性,使用Object.keys方法。

Q:理解Object.prototype.hasOwnProperty()?

对象实例的hasOwnProperty方法返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上。
hasOwnProperty方法是JavaScript之中唯一一个处理对象属性时,不会遍历原型链的方法。

Q:in 运算符和 for…in 循环?

in运算符返回一个布尔值,表示一个对象是否具有某个属性。它不区分该属性是对象自身的属性,还是继承的属性。

in运算符常用于检查一个属性是否存在。

获得对象的所有可枚举属性(不管是自身的还是继承的),可以使用for…in循环。

Q:对象的拷贝?

如果要拷贝一个对象,需要做到下面两件事情。

  1. 确保拷贝后的对象,与原对象具有同样的prototype原型对象。
  2. 确保拷贝后的对象,与原对象具有同样的属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function copyObject(orig) {
var copy = Object.create(Object.getPrototypeOf(orig));
copyOwnPropertiesFrom(copy, orig);
return copy;
}
function copyOwnPropertiesFrom(target, source) {
Object
.getOwnPropertyNames(source)
.forEach(function(propKey) {
var desc = Object.getOwnPropertyDescriptor(source, propKey);
Object.defineProperty(target, propKey, desc);
});
return target;
}

Q:JS如何实现多重继承?

JavaScript 不提供多重继承功能,即不允许一个对象同时继承多个对象。但是,可以通过变通方法,实现这个功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function M1() {
this.hello = 'hello';
}
function M2() {
this.world = 'world';
}
function S() {
M1.call(this);
M2.call(this);
}
// 继承 M1
S.prototype = Object.create(M1.prototype);
// 继承链上加入 M2
Object.assign(S.prototype, M2.prototype);
// 指定构造函数
S.prototype.constructor = S;
var s = new S();
s.hello // 'hello:'
s.world // 'world'

上面代码中,子类S同时继承了父类M1和M2。这种模式又称为 Mixin(混入)。

Q:setTimeout(f, 0)

setTimeout(f, 0)将第二个参数设为0,作用是让f在现有的任务(脚本的同步任务和“消息队列”指定的任务)一结束就立刻执行。也就是说,setTimeout(f, 0)的作用是,尽可能早地执行指定的任务。而并不是会立刻就执行这个任务。