1.javaScript 的数据类型有什么
Undefined、Null、Boolean、Number、String、Object、Symbol(es6– 原始数据类型)。
2. 检测数据类型有什么办法
typeof
typeof xxx 失去的值有以下几种类型:undefined boolean number string object function、symbol,比较简单,不再一一演示了。
这里须要留神的有三点:
typeof null 后果是 object,理论这是 typeof 的一个 bug,null 是原始值,非援用类型
typeof [1, 2] 后果是 object,后果中没有 array 这一项,援用类型除了 function 其余的全部都是 object
typeof Symbol() 用 typeof 获取 symbol 类型的值得到的是 symbol,这是 ES6 新增的知识点
instanceof
用于实例和构造函数的对应。例如判断一个变量是否是数组,应用 typeof 无奈判断,但能够应用 [1, 2] instanceof Array 来判断。因为,[1, 2] 是数组,它的构造函数就是 Array。同理:
function Foo(name) {
this.name = name
}
var foo = new Foo(‘bar’)
console.log(foo instanceof Foo) // true
3. 介绍 js 有哪些内置对象?
Object 是 JavaScript 中所有对象的父对象
数据封装类对象:Object、Array、Boolean、Number 和 String
其余对象:Function、Arguments、Math、Date、RegEx、Error
4. 如何辨别数组和对象?
(1)从原型动手,Array.prototype.isPrototypeOf(obj); 利用 isPrototypeOf()办法,断定 Array 是不是在 obj 的原型链中,如果是,则返回 true, 否则 false。Array.prototype.isPrototype([]) //true
(2)也能够从构造函数动手,利用对向的 constructor 属性
(3)依据对象的 class 属性(类属性),跨原型链调用 toString() 办法。Object.prototype.toString.call(Window);
(4)Array.isArray()办法。
5.null,undefined 的区别?
null 示意一个对象被定义了,值为“空值”;
undefined 示意不存在这个值。
typeof undefined //”undefined”
undefined : 是一个示意 ” 无 ” 的原始值或者说示意 ” 短少值 ”,就是此处应该有一个值,然而还没有定义。当尝试读取时会返回 undefined;
例如变量被申明了,但没有赋值时,就等于 undefined
typeof null //”object”
null : 是一个对象 (空对象, 没有任何属性和办法);
例如作为函数的参数,示意该函数的参数不是对象;
留神:
在验证 null 时,肯定要应用 ===,因为 == 无奈别离 null 和 undefined
undefined 示意 ” 短少值 ”,就是此处应该有一个值,然而还没有定义。典型用法是:
1)变量被申明了,但没有赋值时,就等于 undefined。
2) 调用函数时,应该提供的参数没有提供,该参数等于 undefined。
3)对象没有赋值的属性,该属性的值为 undefined。
4)函数没有返回值时,默认返回 undefined。
null 示意 ” 没有对象 ”,即该处不应该有值。
典型用法是:
1)作为函数的参数,示意该函数的参数不是对象。
2)作为对象原型链的起点。
6. 申明变量和申明函数的晋升有什么区别?
(1) 变量申明晋升:变量申明在进入执行上下文就实现了。
只有变量在代码中进行了申明,无论它在哪个地位上进行申明,js 引擎都会将它的申明放在范畴作用域的顶部;
(2) 函数申明晋升:执行代码之前会先读取函数申明,意味着能够把函数申明放在调用它的语句前面。
只有函数在代码中进行了申明,无论它在哪个地位上进行申明,js 引擎都会将它的申明放在范畴作用域的顶部;
(3) 变量 or 函数申明:函数申明会笼罩变量申明,但不会笼罩变量赋值。
同一个名称标识 a,即有变量申明 var a,又有函数申明 function a() {},不论二者申明的程序,函数申明会笼罩变量申明,也就是说,此时 a 的值是申明的函数 function a() {}。留神:如果在变量申明的同时初始化 a,或是之后对 a 进行赋值,此时 a 的值变量的值。eg: var a; var c = 1; a = 1; function a() { return true;} console.log(a);
原型,原型链
1.JavaScript 原型,原型链 ? 有什么特点?
原型
每个对象都会在其外部初始化一个属性,就是 prototype(原型)
应用 hasOwnProperty() 能够判断这个属性是不是对象自身的属性
问题:Javascript 中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
hasOwnProperty
javaScript 中 hasOwnProperty 函数办法是返回一个布尔值,指出一个对象是否具备指定名称的属性。此办法无奈查看该对象的原型链中是否具备该属性;该属性必须是对象自身的一个成员。
应用办法:
object.hasOwnProperty(proName)
其中参数 object 是必选项。一个对象的实例。
proName 是必选项。一个属性名称的字符串值。
如果 object 具备指定名称的属性,那么 JavaScript 中 hasOwnProperty 函数办法返回 true,反之则返回 false。
原型链
当咱们在拜访一个对象的属性时,如果这个对象外部不存在这个属性,那么他就会去 prototype 里找这个属性,这个 prototype 又会有本人的 prototype,于是就这样始终找上来,找到 Object.__proto__为止,找不到就返回 unde 也就是咱们平时所说的原型链的概念。
关系:instance.constructor.prototype = instance.__proto__
特点:
JavaScript 对象是通过援用来传递的,咱们创立的每个新对象实体中并没有一份属于本人的原型正本。当咱们批改原型时,与之相干的对象也会继承这一扭转。
当咱们须要一个属性的时,Javascript 引擎会先看以后对象中是否有这个属性,如果没有的话,就会查找他的 Prototype 对象是否有这个属性,如此递推上来,始终检索到 Object 内建对象。
所有的援用类型(数组、对象、函数),都具备对象个性,即可自在扩大属性(null 除外)
所有的援用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个一般的对象
所有的函数,都有一个 prototype 属性,属性值也是一个一般的对象
所有的援用类型(数组、对象、函数),__proto__属性值指向它的构造函数的 prototype 属性值
原型链中的 this
所有从原型或更高级原型中失去、执行的办法,其中的 this 在执行时,就指向了以后这个触发事件执行的对象。
闭包
闭包的造成与变量的作用域以及变量的生存周期有亲密的关系
1. 变量的作用域
在 js 中咱们把作用域分为全局作用域和部分作用域,全局作用域就是 window,在没有块级作用域概念的时候,每一个函数都是一个部分作用域。
其实变量的作用域,就说指变量的无效范畴。咱们最长说的就是在函数中申明的变量作用域。
当在函数中申明一个变量的时候,如果扭转量没有用 var 关键字去定义那么该变量就是一个全局变量,然而这样做最容易造成命名抵触。
另一种状况就是应用 var 申明的变量,这时候的变量就是局部变量,只有在该函数外部能够拜访,在函数里面是拜访不到的
在 javascript 中,函数能够用来发明函数作用域。在函数中搜寻变量的时候,如果该函数当中没有这个变量,那么这次搜寻过程会随着代码执行环境创立的作用域链往外层逐层搜寻,始终搜寻到 window 对象为止,找不到就会抛出一个为定义的谬误。而这种从内到外逐层查找的关系在 js 中咱们称为作用域链
2. 变量的生存周期
除了变量作用域之外,另外一个跟闭包无关的概念就是变量的生存周期,对于全局变量来说,全局变量的生存周期是永恒的,除非咱们被动销毁这个全局变量,而对于函数外部的应用 var 申明的变量来说,当退出函数是,这些变量就会随着函数的完结而销毁。
3. 闭包的造成
Javascript 容许应用外部函数,能够将函数定义和函数表达式放在另一个函数的函数体内。而且,外部函数能够拜访它所在的内部函数申明的局部变量、参数以及申明的其余外部函数。当其中一个这样的外部函数在蕴含它们的内部函数之外被调用时,就会造成闭包。常见的闭包写法就是简略的函数套函数,通过另一个函数拜访这个函数的局部变量, 利用闭包能够冲破作用域链,将函数外部的变量和办法传递到内部,连续变量的生命。应用闭包能够缩小全局环境的净化,也可用连续变量的生命。
4. 闭包的实用场景
闭包的实用场景十分宽泛,首先从闭包的长处登程就是:
缩小全局环境的净化生成独立的运行环境
模块化就是利用这个特点对不同的模块都有本人独立的运行环境,不会和全局抵触,模块和模块之间通过抛出的接口进行依赖应用
以及像咱们罕用的 jquery 类库(防止和全局抵触应用闭包实现本人独立的环境)
能够通过返回其余函数的形式冲破作用域链
能够利用这个性能做一些值的缓存工作,例如常见的设计模式(单例模式),以及当初比拟火的框架 vue 中的计算属性
其实当遇到以下场景的时候都能够应用闭包
1) 保护函数内的变量平安, 防止全局变量的净化。
2) 维持一个变量不被回收。
3) 封装模块
5. 闭包的毛病
因为闭包会使得函数中的变量都被保留在内存中,内存耗费很大。所以在闭包不必之后,将不应用的局部变量删除,使其被回收。在 IE 中可能导致内存泄露,即无奈回收驻留在内存中的元素,这时候须要手动开释。
6. 内存泄露
内存透露指一块被调配的内存既不能应用,又不能回收,直到浏览器过程完结。
呈现起因:
1) 循环援用:含有 DOM 对象的循环援用将导致大部分以后支流浏览器内存泄露。循环 援用,简略来说如果 a 援用了 b,b 又援用了 a,a 和 b 就形成了循环援用。
2) JS 闭包:闭包,函数返回了外部函数还能够持续拜访内部办法中定义的公有变量。
3) Dom 泄露,当原有的 DOM 被移除时,子结点援用没有被移除则无奈回收。
7.JavaScript 垃圾回收机制
Javascript 中,如果一个对象不再被援用,那么这个对象就会被 GC(garbage collection) 回收。如果两个对象相互援用,而不再被第 3 者所援用,那么这两个相互援用的对象也会被回收。垃圾回收不是时时的,因为其开销比拟大,所以垃圾回收器会依照固定的工夫距离周期性的执行。
函数 a 被 b 援用,b 又被 a 外的 c 援用,这就是为什么函数 a 执行后不会被回收的起因。
8. 垃圾回收的两个办法:
标记革除法:
1) 垃圾回收机制给存储在内存中的所有变量加上标记,而后去掉环境中的变量以及被环境中变量所援用的变量(闭包)。
2) 操作 1 之后内存中仍存在标记的变量就是要删除的变量,垃圾回收机制将这些带有标记的变量回收。
援用计数法:
1) 垃圾回收机制给一个变量一个援用次数,当申明了一个变量并将一个援用类型赋值给该变量的时候这个值的援用次数就加 1。
2) 当该变量的值变成了另外一个值,则这个值得引用次数减 1。
3) 当这个值的援用次数变为 0 的时候,阐明没有变量在应用,垃圾回收机制会在运行的时候清理掉援用次数为 0 的值占用的空间。
JS 运行机制
JavaScript 引擎是单线程运行的, 浏览器无论在什么时候都只且只有一个线程在运行 JavaScript 程序. 浏览器的内核是多线程的,它们在内核制控下相互配合以放弃同步,一个浏览器至多实现三个常驻线程:javascript 引擎线程,GUI 渲染线程,浏览器事件触发线程。这些异步线程都会产生不同的异步的事件.
1) javascript 引擎是基于事件驱动单线程执行的,JS 引擎始终期待着工作队列中工作的到来,而后加以解决,浏览器无论什么时候都只有一个 JS 线程在运行 JS 程序。
2) GUI 渲染线程负责渲染浏览器界面,当界面须要重绘(Repaint)或因为某种操作引发回流 (reflow) 时, 该线程就会执行。但须要留神 GUI 渲染线程与 JS 引擎是互斥的,当 JS 引擎执行时 GUI 线程会被挂起,GUI 更新会被保留在一个队列中等到 JS 引擎闲暇时立刻被执行。
3) 事件触发线程,当一个事件被触发时该线程会把事件增加到待处理队列的队尾,期待 JS 引擎的解决。这些事件可来自 JavaScript 引擎以后执行的代码块如 setTimeOut、也可来自浏览器内核的其余线程如鼠标点击、AJAX 异步申请等,但因为 JS 的单线程关系所有这些事件都得排队期待 JS 引擎解决。(当线程中没有执行任何同步代码的前提下才会执行异步代码)
当程序启动时, 一个过程被创立,同时也运行一个线程, 即为主线程,js 的运行机制为单线程
程序中跑两个线程,一个负责程序自身的运行,作为主线程;另一个负责主线程与其余线程的的通信,被称为“Event Loop 线程 ”。每当遇到异步工作,交给 EventLoop 线程,而后本人往后运行,等到主线程运行完后,再去 EventLoop 线程拿后果。
1)所有工作都在主线程上执行,造成一个执行栈(execution context stack)。
2)主线程之外,还存在一个 ” 工作队列 ”(task queue)。零碎把异步工作放到 ” 工作队列 ” 之中,而后继续执行后续的工作。
3)一旦 ” 执行栈 ” 中的所有工作执行结束,零碎就会读取 ” 工作队列 ”。如果这个时候,异步工作曾经完结了期待状态,就会从 ” 工作队列 ” 进入执行栈,复原执行。
4)主线程一直反复下面的第三步。
“ 回调函数 ”(callback),就是那些会被主线程挂起来的代码。异步工作必须指定回调函数,当异步工作从 ” 工作队列 ” 回到执行栈,回调函数就会执行。” 工作队列 ” 是一个先进先出的数据结构,排在后面的事件,优先返回主线程。主线程的读取过程基本上是主动的,只有执行栈一清空,” 工作队列 ” 上第一位的事件就主动返回主线程。
主线程从 ” 工作队列 ” 中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为 Event Loop。
从主线程的角度看,一个异步过程包含上面两个因素:
发动函数 (或叫注册函数)A
回调函数 callbackFn
它们都是在主线程上调用的,其中注册函数用来发动异步过程,回调函数用来处理结果。
异步过程有:
相似 onclick 等,由浏览器内核的 DOM binding 模块解决,事件触发时,回调函数增加到工作队列中;
setTimeout 等,由浏览器内核的 Timer 模块解决,工夫达到时,回调函数增加到工作队列中;
Ajax,由浏览器内核的 Network 模块解决,网络申请返回后,增加到工作队列中。
例如 setTimeout(fn, 1000),其中的 setTimeout 就是异步过程的发动函数,fn 是回调函数。用一句话概括:工作线程将音讯放到音讯队列,主线程通过事件循环过程去取音讯。
音讯队列:音讯队列是一个先进先出的队列,它外面寄存着各种音讯。
事件循环:事件循环是指主线程反复从音讯队列中取音讯、执行的过程。
流程如下:
1) 主线程读取 js 代码, 造成相应的堆和执行栈, 执行同步工作
2) 当主线程遇到异步工作,,指定给异步过程解决, 同时继续执行同步工作
3) 当异步过程处理完毕后,将相应的异步工作推入到工作队列首部
4) 主线程工作处理完毕后,,查问工作队列,则取出一个工作队列推入到主线程的执行栈
5) 反复执行第 2、3、4 步,这就称为事件循环
JS-Web-API 知识点与高频考题解析
BOM
BOM(浏览器对象模型)是浏览器自身的一些信息的设置和获取,例如获取浏览器的宽度、高度,设置让浏览器跳转到哪个地址。
navigator:获取浏览器个性(即俗称的 UA)而后辨认客户端
location:获取网址、协定、path、参数、hash 等
history:操作浏览器的历史纪录,(后退,后退等性能)
1. 什么是 window 对象? 什么是 document 对象?
window: 它是一个顶层对象, 而不是另一个对象的属性,即浏览器的窗口。
document: 代表整个 HTML 文档, 可用来拜访页面中的所有元素
Window 对象示意以后浏览器的窗口,是 JavaScript 的顶级对象。咱们创立的所有对象、函数、变量都是 Window 对象的成员。
Window 对象的办法和属性是在全局范畴内无效的。
Document 对象是 HTML 文档的根节点与所有其余节点(元素节点,文本节点,属性节点, 正文节点)
Document 对象使咱们能够通过脚本对 HTML 页面中的所有元素进行拜访
Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行拜访
2. 事件是?IE 与火狐的事件机制有什么区别?如何阻止冒泡?
1) 咱们在网页中的某个操作(有的操作对应多个事件)。例如:当咱们点击一个按钮就会产生一个事件。是能够被 JavaScript 侦测到的行为。
2) 事件处理机制:IE 是事件冒泡、Firefox 同时反对两种事件模型,也就是:捕捉型事件和冒泡型事件;
3) ev.stopPropagation();(旧 ie 的办法 ev.cancelBubble = true;)
3. 解释一下事件代理
事件代理的原理其实就和作用域链的原理差不多,然而事件代理是利用事件的冒泡原理来实现的,事件代理就是通过给先人元素增加事件,通过事件指标对象开始向上查找找到匹配的子节点为止,如果找不到则到绑定事件的那个先人元素为止,找到了就触发事件,并且能够通过 js 中 call 和 apply 来扭转触发事件函数中的 this 为以后绑定节点,也是通过一层一层逐层向上的形式进行匹配查找而触发对应事件,益处就是能够使后增加的 dom 元素也同样有之前存在元素的事件,jquery 中能够应用 on,delegate,live 实现的,不过在 jquery1.7 版本当前吧 live 给破除了,起因就是 live 绑定事件的先人元素是整个 html 页面的根节点,所以性能耗费比拟大,在后边的版本中给删除了,应用 on,delegate 代替
长处:
使代码简洁
缩小浏览器的内存占用
毛病:
使用不当会造成事件在不应该触发时触发
function bindEvent(elem, type, selector, fn) {
// 这样解决,可接管两种调用形式 bindEvent(div1, 'click', 'a', function () {...}) 和 bindEvent(div1, 'click', function () {...}) 这两种
if (fn == null) {
fn = selector
selector = null
}
// 绑定事件
elem.addEventListener(type, function (e) {
var target
if (selector) {
// 有 selector 阐明须要做事件代理
// 获取触发工夫的元素,即 e.target
target = e.target
// 看是否合乎 selector 这个条件
if (target.matches(selector)) {fn.call(target, e)
}
} else {
// 无 selector,阐明不须要事件代理
fn(e)
}
})
}
// 应用代理,bindEvent 多一个 ‘a’ 参数
var div1 = document.getElementById(‘div1’)
bindEvent(div1, ‘click’, ‘a’, function (e) {
console.log(this.innerHTML)
})
// 不应用代理
var a = document.getElementById(‘a1’)
bindEvent(div1, ‘click’, function (e) {
console.log(a.innerHTML)
})
4.offsetWidth/offsetHeight,clientWidth/clientHeight 与 scrollWidth/scrollHeight 的区别
offsetWidth/offsetHeight 返回值蕴含 content + padding + border,成果与 e.getBoundingClientRect() 雷同
clientWidth/clientHeight 返回值只蕴含 content + padding,如果有滚动条,也不蕴含滚动条
scrollWidth/scrollHeight 返回值蕴含 content + padding + 溢出内容的尺寸
5.focus/blur 与 focusin/focusout 的区别与分割
focus/blur 不冒泡,focusin/focusout 冒泡
focus/blur 兼容性好,focusin/focusout 在除 FireFox 外的浏览器下都保持良好兼容性,如需应用事件托管,可思考在 FireFox 下应用事件捕捉 elem.addEventListener(‘focus’, handler, true)
可取得焦点的元素:
window
链接被点击或键盘操作
表单空间被点击或键盘操作
设置 tabindex 属性的元素被点击或键盘操作
6.mouseover/mouseout 与 mouseenter/mouseleave 的区别与分割
mouseover/mouseout 是规范事件,所有浏览器都反对;mouseenter/mouseleave 是 IE5.5 引入的特有事件起初被 DOM3 规范驳回,古代规范浏览器也反对
mouseover/mouseout 是冒泡事件;mouseenter/mouseleave 不冒泡。须要为多个元素监听鼠标移入 / 出事件时,举荐 mouseover/mouseout 托管,进步性能
规范事件模型中 event.target 示意产生移入 / 出的元素,vent.relatedTarget 对应移出 / 如元素;在老 IE 中 event.srcElement 示意产生移入 / 出的元素,event.toElement 示意移出的指标元素,event.fromElement 示意移入时的起源元素
7. 介绍 DOM0,DOM2,DOM3 事件处理形式区别
DOM0 级事件处理形式:
btn.onclick = func;
btn.onclick = null;
DOM2 级事件处理形式:
btn.addEventListener(‘click’, func, false);
btn.removeEventListener(‘click’, func, false);
btn.attachEvent(“onclick”, func);
btn.detachEvent(“onclick”, func);
DOM3 级事件处理形式:
eventUtil.addListener(input, “textInput”, func);
eventUtil 是自定义对象,textInput 是 DOM3 级事件
8. 事件的三个阶段
捕捉、指标、冒泡
js 的冒泡 (Bubbling Event) 和捕捉 (Capture Event) 的区别
冒泡型事件:事件依照从最特定的事件指标到最不特定的事件指标 (document 对象) 的程序触发。
捕捉型事件 (event capturing):事件从最不准确的对象(document 对象) 开始触发,而后到最准确(也能够在窗口级别捕捉事件,不过必须由开发人员特地指定)。
DOM 事件流:同时反对两种事件模型:捕捉型事件和冒泡型事件,然而,捕捉型事件先产生。两种事件流会涉及 DOM 中的所有对象,从 document 对象开始,也在 document 对象完结。
事件捕捉
当你应用事件捕捉时,父级元素先触发,子级元素后触发,即 div 先触发,p 后触发。
事件冒泡
当你应用事件冒泡时,子级元素先触发,父级元素后触发,即 p 先触发,div 后触发。
阻止冒泡
在 W3c 中,应用 stopPropagation()办法
在 IE 下设置 cancelBubble = true;
在捕捉的过程中 stopPropagation();后,前面的冒泡过程也不会产生了。
阻止捕捉
阻止事件的默认行为,例如 click 后的跳转
在 W3c 中,应用 preventDefault()办法;
在 IE 下设置 window.event.returnValue = false;
9. 介绍事件“捕捉”和“冒泡”执行程序和事件的执行次数?
依照 W3C 规范的事件:首是进入捕捉阶段,直到达到目标元素,再进入冒泡阶段
事件执行次数(DOM2-addEventListener):元素上绑定事件的个数
留神 1:前提是事件被的确触发
留神 2:事件绑定几次就算几个事件,即便类型和性能齐全一样也不会“笼罩”
事件执行程序:判断的要害是否指标元素
非指标元素:依据 W3C 的规范执行:捕捉 -> 指标元素 -> 冒泡(不根据事件绑定程序)
指标元素:根据事件绑定程序:先绑定的事件先执行(不根据捕捉冒泡规范)
最终程序:父元素捕捉 -> 指标元素事件 1 -> 指标元素事件 2 -> 子元素捕捉 -> 子元素冒泡 -> 父元素冒泡
留神:子元素事件执行前提 事件的确“落”到子元素布局区域上,而不是简略的具备嵌套关系
在一个 DOM 上同时绑定两个点击事件:一个用捕捉,一个用冒泡。事件会执行几次,先执行冒泡还是捕捉?
该 DOM 上的事件如果被触发,会执行两次(执行次数等于绑定次数)
如果该 DOM 是指标元素,则按事件绑定程序执行,不辨别冒泡 / 捕捉
如果该 DOM 是处于事件流中的非指标元素,则先执行捕捉,后执行冒泡
10.window.onload 和 document.DOMContentLoaded (注:$(document).ready()) 的区别?
个别状况下,DOMContentLoaded 事件要在 window.onload 之前执行,当 DOM 树构建实现的时候就会执行 DOMContentLoaded 事件,而 window.onload 是在页面载入实现的时候,才执行,这其中包含图片等元素。大多数时候咱们只是想在 DOM 树构建实现后,绑定事件到元素,咱们并不需要图片元素,加上有时候加载外域图片的速度十分迟缓。
DOM
讲 DOM 先从 HTML 讲起,讲 HTML 先从 XML 讲起。XML 是一种可扩大的标记语言,所谓可扩大就是它能够形容任何结构化的数据,它是一棵树!
1.documen.write 和 innerHTML 的区别
document.write 只能重绘整个页面
innerHTML 能够重绘页面的一部分
2.DOM 操作——怎么增加、移除、挪动、复制、创立和查找节点?
1)创立新节点
createDocumentFragment() // 创立一个 DOM 片段
createElement() // 创立一个具体的元素
createTextNode() // 创立一个文本节点
2)增加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() // 在已有的子节点前插入一个新的子节点
3)查找
getElementsByTagName() // 通过标签名称
getElementsByName() // 通过元素的 Name 属性的值(IE 容错能力较强,会失去一个数组,其中包含 id 等于 name 值的)
getElementById() // 通过元素 Id,唯一性
3.attribute 和 property 的区别是什么?
attribute 是 dom 元素在文档中作为 html 标签领有的属性;
property 就是 dom 元素在 js 中作为对象领有的属性。
所以:
对于 html 的规范属性来说,attribute 和 property 是同步的,是会自动更新的,
然而对于自定义的属性来说,他们是不同步的,
4.src 和 href 的区别
src 用于替换以后元素,href 用于在以后文档和援用资源之间确立分割。
src 是 source 的缩写,指向内部资源的地位,指向的内容将会嵌入到文档中以后标签所在位置;在申请 src 资源时会将其指向的资源下载并利用到文档内,当浏览器解析到该元素时,会暂停其余资源的下载和解决,直到将该资源加载、编译、执行结束,图片和框架等元素也如此,相似于将所指向资源嵌入以后标签内。这也是为什么将 js 脚本放在底部而不是头部。
Src source, 指向内部资源的地位, 如果咱们增加 <script src =”js.js”></script> 浏览器会暂停其余资源的下载和解决, 直到该资源加载, 编译, 执行结束(图片和框架也是如此), 这也就是为什么 js 脚本要放在底部。
src 用于替换以后元素,href 用于在以后文档和引入资源之间建立联系。
对象
1,JavaScript 继承的几种实现形式?
1)构造函数继承,应用 call 和 apply 两个办法的个性能够实现,扭转办法中的 this
2)原型链继承
3)组合式继承
2.javascript 创建对象的几种形式?
javascript 创建对象简略的说, 无非就是应用内置对象或各种自定义对象,当然还能够用 JSON;但写法有很多种,也能混合应用。
1) 对象字面量的形式 person={firstname:”Mark”,lastname:”Yun”,age:25,eyecolor:”black”};
2) 用 function 来模仿无参的构造函数
function Person(){}
var person=new Person();// 定义一个 function,如果应用 new"实例化", 该 function 能够看作是一个 Class
person.name=“Mark";
person.age="25";
person.work=function(){alert(person.name+"hello...");
}
person.work();
3) 用 function 来模仿参构造函数来实现(用 this 关键字定义结构的上下文属性)
function Pet(name,age,hobby){
this.name=name;//this 作用域:以后对象
this.age=age;
this.hobby=hobby;
this.eat=function(){alert("我叫"+this.name+", 我喜爱"+this.hobby+", 是个程序员");
}
}
var maidou =new Pet("麦兜",25,"coding");// 实例化、创建对象
maidou.eat();// 调用 eat 办法
4) 用工厂形式来创立(内置对象)
var wcDog =new Object();
wcDog.name="旺财";
wcDog.age=3;
wcDog.work=function(){alert("我是"+wcDog.name+", 汪汪汪......");
}
wcDog.work();
5、用原型形式来创立
function Dog(){}
Dog.prototype.name="旺财";
Dog.prototype.eat=function(){alert(this.name+"是个吃货");}
var wangcai =new Dog();
wangcai.eat();
5) 用混合形式来创立
function Car(name,price){
this.name=name;
this.price=price;
}
Car.prototype.sell=function(){alert("我是"+this.name+",我当初卖"+this.price+"万元");
}
var camry =new Car("凯美瑞",27);
camry.sell();
3. 谈谈 This 对象的了解。
this 分为几个不同的应用场景,在 function 中 this 指的的是 window,如果是实用 new 调用的话 this 指的是以后的实例化对象,在事件调用函数中 this 指的调用事件的 window 非凡的是在 IE 中的 attachEvent 中的 this 总是指向全局对象 Window;,在定时器中 this 指的是 window,在 es6 中有一个箭头函数,在箭头函数中 this 永远指向的是父级对象,this 也是能够扭转的,在 js 中 call, apply, bind 都能够扭转 this 的指向,call, apply 都是执行一个函数并且扭转 this,区别就是参数传递不一样,而 bind 是返回一个绑定 this 之后的新函数
4.javascript 代码中的 ”use strict”; 是什么意思 ? 应用它区别是什么?
use strict 是一种 ECMAscript 5 增加的(严格)运行模式, 这种模式使得 Javascript 在更严格的条件下运行,
使 JS 编码更加规范化的模式, 打消 Javascript 语法的一些不合理、不谨严之处,缩小一些怪异行为。
默认反对的蹩脚个性都会被禁用,比方不能用 with,也不能在意外的状况下给全局变量赋值;
全局变量的显示申明, 函数必须申明在顶层,不容许在非函数代码块内申明函数,arguments.callee 也不容许应用;
打消代码运行的一些不平安之处,保障代码运行的平安, 限度函数中的 arguments 批改,严格模式下的 eval 函数的行为和非严格模式的也不雷同;
进步编译器效率,减少运行速度;
为将来新版本的 Javascript 标准化做铺垫。
5.JSON 的理解?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格局。
它是基于 JavaScript 的一个子集。数据格式简略, 易于读写, 占用带宽小
如:{“age”:”12″, “name”:”back”}
JSON 字符串转换为 JSON 对象:
var obj =eval(‘(‘+ str +’)’);
var obj = str.parseJSON();
var obj = JSON.parse(str);
JSON 对象转换为 JSON 字符串:
var last=obj.toJSONString();
var last=JSON.stringify(obj);
- .call() 和 .apply() 的区别?
7. 什么是函数节流?介绍一下利用场景和原理?
函数节流 (throttle) 是指阻止一个函数在很短时间距离内间断调用。只有当上一次函数执行后达到规定的工夫距离,能力进行下一次调用。但要保障一个累计最小调用距离(否则拖拽类的节流都将无间断成果)
函数节流用于 onresize, onscroll 等短时间内会屡次触发的事件
函数节流的原理:应用定时器做工夫节流。当触发一个事件时,先用 setTimout 让这个事件提早一小段时间再执行。如果在这个工夫距离内又触发了事件,就 clearTimeout 原来的定时器,再 setTimeout 一个新的定时器反复以上流程。
函数节流简略实现:
function throttle(method, context) {
clearTimeout(methor.tId);
method.tId = setTimeout(function(){method.call(context);
},100); // 两次调用至多距离 100ms
}
// 调用
window.onresize = function(){
throttle(myFunc, window);
}
8.new 操作符具体干了什么?
创立实例对象,this 变量援用该对象,同时还继承了构造函数的原型
属性和办法被退出到 this 援用的对象中
新创建的对象由 this 所援用,并且最初隐式的返回 this
new 共经验了四个过程。
var fn = function () {};
var fnObj = new fn();
1)创立了一个空对象
var obj = new object();
2)设置原型链
obj._proto_ = fn.prototype;
3)让 fn 的 this 指向 obj,并执行 fn 的函数体
var result = fn.call(obj);
4)判断 fn 的返回值类型,如果是值类型,返回 obj。如果是援用类型,就返回这个援用类型的对象。
if (typeof(result) == “object”){
fnObj = result;
} else {
fnObj = obj;}
兼容与优化
1. 页面重构怎么操作?
网站重构:在不扭转内部行为的前提下,简化构造、增加可读性,而在网站前端保持一致的行为。
也就是说是在不扭转 UI 的状况下,对网站进行优化,在扩大的同时保持一致的 UI。
对于传统的网站来说重构通常是:
表格 (table) 布局改为 DIV+CSS
使网站前端兼容于古代浏览器 (针对于不合标准的 CSS、如对 IE6 无效的)
对于挪动平台的优化
针对于 SEO 进行优化
深层次的网站重构应该思考的方面
缩小代码间的耦合
让代码放弃弹性
严格按标准编写代码
设计可扩大的 API
代替旧有的框架、语言 (如 VB)
加强用户体验
通常来说对于速度的优化也蕴含在重构中
压缩 JS、CSS、image 等前端资源 (通常是由服务器来解决)
程序的性能优化 (如数据读写)
采纳 CDN 来减速资源加载
对于 JS DOM 的优化
HTTP 服务器的文件缓存
2. 列举 IE 与其余浏览器不一样的个性?
1)事件不同之处:
1-1,触发事件的元素被认为是指标(target)。而在 IE 中,指标蕴含在 event 对象的 srcElement 属性;
1-2,获取字符代码、如果按键代表一个字符(shift、ctrl、alt 除外),IE 的 keyCode 会返回字符代码(Unicode),DOM 中按键的代码和字符是拆散的,要获取字符代码,须要应用 charCode 属性;
1-3,阻止某个事件的默认行为,IE 中阻止某个事件的默认行为,必须将 returnValue 属性设置为 false,Mozilla 中,须要调用 preventDefault() 办法;
1-4,进行事件冒泡,IE 中阻止事件进一步冒泡,须要设置 cancelBubble 为 true,Mozzilla 中,须要调用 stopPropagation();
3. 什么叫优雅降级和渐进加强?
优雅降级:Web 站点在所有旧式浏览器中都能失常工作,如果用户应用的是老式浏览器,则代码会针对旧版本的 IE 进行降级解决了, 使之在新式浏览器上以某种模式降级体验却不至于齐全不能用。
如:border-shadow
渐进加强:从被所有浏览器反对的基本功能开始,逐渐地增加那些只有新版本浏览器才反对的性能, 向页面减少不影响根底浏览器的额定款式和性能的。当浏览器反对时,它们会主动地出现进去并发挥作用。
如:默认应用 flash 上传,但如果浏览器反对 HTML5 的文件上传性能,则应用 HTML5 实现更好的体验;
4. 说说严格模式的限度
严格模式次要有以下限度:
变量必须申明后再应用
函数的参数不能有同名属性,否则报错
不能应用 with 语句
不能对只读属性赋值,否则报错
不能应用前缀 0 示意八进制数,否则报错
不能删除不可删除的属性,否则报错
不能删除变量 delete prop,会报错,只能删除属性 delete global[prop]
eval 不会在它的外层作用域引入变量
eval 和 arguments 不能被从新赋值
arguments 不会主动反映函数参数的变动
不能应用 arguments.callee
不能应用 arguments.caller
禁止 this 指向全局对象
不能应用 fn.caller 和 fn.arguments 获取函数调用的堆栈
减少了保留字(比方 protected、static 和 interface)
设立 ” 严格模式 ” 的目标,次要有以下几个:
打消 Javascript 语法的一些不合理、不谨严之处,缩小一些怪异行为;
打消代码运行的一些不平安之处,保障代码运行的平安;
进步编译器效率,减少运行速度;
为将来新版本的 Javascript 做好铺垫。
注:通过测试 IE6,7,8,9 均不反对严格模式。
5. 检测浏览器版本版本有哪些形式?
依据 navigator.userAgent // UA.toLowerCase().indexOf(‘chrome’)
依据 window 对象的成员 // ‘ActiveXObject’ in window
6. 总结前端性能优化的解决方案
优化准则和方向
性能优化的准则是以更好的用户体验为规范,具体就是实现上面的指标:
多应用内存、缓存或者其余办法
缩小 CPU 和 GPU 计算,更快展示
优化的方向有两个:
缩小页面体积,晋升网络加载
优化页面渲染
缩小页面体积,晋升网络加载
动态资源的压缩合并(JS 代码压缩合并、CSS 代码压缩合并、雪碧图)
动态资源缓存(资源名称加 MD5 戳)
应用 CDN 让资源加载更快
优化页面渲染
CSS 放后面,JS 放前面
懒加载(图片懒加载、下拉加载更多)
缩小 DOM 查问,对 DOM 查问做缓存
缩小 DOM 操作,多个操作尽量合并在一起执行(DocumentFragment)
事件节流
尽早执行操作(DOMContentLoaded)
应用 SSR 后端渲染,数据间接输入到 HTML 中,缩小浏览器应用 JS 模板渲染页面 HTML 的工夫
7. 图片懒加载与预加载
图片懒加载的原理就是临时不设置图片的 src 属性,而是将图片的 url 暗藏起来,比方先写在 data-src 外面,等某些事件触发的时候 (比方滚动到底部,点击加载图片) 再将图片实在的 url 放进 src 属性外面,从而实现图片的提早加载
图片预加载是指在一些须要展现大量图片的网站,实现图片的提前加载。从而晋升用户体验。罕用的形式有两种,一种是暗藏在 css 的 background 的 url 属性外面,一种是通过 javascript 的 Image 对象设置实例对象的 src 属性实现图片的预加载。相干代码如下:
CSS 预加载图片形式:
preload-01 {background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
preload-02 {background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
preload-03 {background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
Javascript 预加载图片的形式:
function preloadImg(url) {
var img = new Image();
img.src = url;
if(img.complete) {
// 接下来能够应用图片了
//do something here
} else {
img.onload = function() {
// 接下来能够应用图片了
//do something here
};
}
}
5. 形容浏览器的渲染过程,DOM 树和渲染树的区别?
浏览器的渲染过程:
解析 HTML 构建 DOM(DOM 树),并行申请 css/image/js
CSS 文件下载实现,开始构建 CSSOM(CSS 树)
CSSOM 构建完结后,和 DOM 一起生成 Render Tree(渲染树)
布局 (Layout):计算出每个节点在屏幕中的地位
显示 (Painting):通过显卡把页面画到屏幕上
DOM 树 和 渲染树 的区别:
DOM 树与 HTML 标签一一对应,包含 head 和暗藏元素
渲染树不包含 head 和暗藏元素,大段文本的每一个行都是独立节点,每一个节点都有对应的 css 属性
7. 重绘和回流(重排)的区别和关系?
重绘:当渲染树中的元素外观(如:色彩)产生扭转,不影响布局时,产生重绘
回流:当渲染树中的元素的布局(如:尺寸、地位、暗藏 / 状态状态)产生扭转时,产生重绘回流
留神:JS 获取 Layout 属性值(如:offsetLeft、scrollTop、getComputedStyle 等)也会引起回流。因为浏览器须要通过回流计算最新值
回流必将引起重绘,而重绘不肯定会引起回流
8. 如何最小化重绘 (repaint) 和回流 (reflow)?
须要要对元素进行简单的操作时,能够先暗藏(display:”none”),操作实现后再显示
须要创立多个 DOM 节点时,应用 DocumentFragment 创立完后一次性的退出 document
缓存 Layout 属性值,
如:var left = elem.offsetLeft; 这样,屡次应用 left 只产生一次回流
尽量避免用 table 布局(table 元素一旦触发回流就会导致 table 里所有的其它元素回流)
防止应用 css 表达式(expression),因为每次调用都会从新计算值(包含加载页面)
尽量应用 css 属性简写,如:用 border 代替 border-width, border-style, border-color
批量批改元素款式:elem.className 和 elem.style.cssText 代替 elem.style.xxx
9.script 的地位是否会影响首屏显示工夫?
在解析 HTML 生成 DOM 过程中,js 文件的下载是并行的,不须要 DOM 解决到 script 节点。因而,script 的地位不影响首屏显示的开始工夫。
浏览器解析 HTML 是自上而下的线性过程,script 作为 HTML 的一部分同样遵循这个准则
因而,script 会提早 DomContentLoad,只显示其上局部首屏内容,从而影响首屏显示的实现工夫
存储
cookie
cookie 自身不是用来做服务器端存储的(计算机领域有很多这种“狗拿耗子”的例子,例如 CSS 中的 float),它是设计用来在服务器和客户端进行信息传递的,因而咱们的每个 HTTP 申请都带着 cookie。然而 cookie 也具备浏览器端存储的能力(例如记住用户名和明码),因而就被开发者用上了。
应用起来也非常简单,document.cookie = …. 即可。
然而 cookie 有它致命的毛病:
存储量太小,只有 4KB
所有 HTTP 申请都带着,会影响获取资源的效率
API 简略,须要封装能力用
locationStorage 和 sessionStorage
起初,HTML5 规范就带来了 sessionStorage 和 localStorage,先拿 localStorage 来说,它是专门为了浏览器端缓存而设计的。
其长处有:
存储量增大到 5MB
不会带到 HTTP 申请中
API 实用于数据存储 localStorage.setItem(key, value) localStorage.getItem(key)
sessionStorage 的区别就在于它是依据 session 过来工夫而实现,而 localStorage 会永恒无效,利用场景不同。例如,一些须要及时生效的重要信息放在 sessionStorage 中,一些不重要然而不常常设置的信息,放在 localStorage 中。
es6/7
1. 说说对 es6 的了解(说一下 es6,晓得 es6 吗)
语法糖(箭头函数,类的定义,继承),以及一些新的扩大(数组,字符串,对象,办法等),对作用域的从新定义,以及异步编程的解决方案(promise,async,await)、解构赋值的呈现
2.ES6 罕用个性
变量定义 (let 和 const, 可变与不可变,const 定义对象的非凡状况)
解构赋值
模板字符串
数组新 API(例:Array.from(),entries(),values(),keys())
箭头函数(rest 参数,扩大运算符,:: 绑定 this)
Set 和 Map 数据结构(set 实例成员值惟一存储 key 值,map 实例存储键值对(key-value))
Promise 对象(前端异步解决方案进化史,generator 函数,async 函数)
Class 语法糖(super 关键字)
3. 说说你对 Promise 的了解
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件监听——更正当和更弱小。Promise 有三种状态:pending(进行中)、fulfilled(已胜利)和 rejected(已失败)。然而无奈获取到 pending 状态,在 promise 中承受两个内置参数别离是 resolve(胜利)和 reject(失败),Promise 实例生成当前,能够用 then 办法别离指定 resolved 状态和 rejected 状态的回调函数。then 办法能够传递两个回调函数第一个是胜利,第二个是失败,失败回调也能够应用 promise 的 catch 办法回调,promise 还有一个弱小的性能那就是 all 办法能够组合多个 promise 实例,包装成一个新的 Promise 实例。
4. 介绍一下 async 和 await;
async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而 await 会期待这个 Promise 实现,并将其 resolve 的后果返回进去。
async / await 是 ES7 的重要个性之一,也是目前社区里公认的优良异步解决方案。目前 async / await 在 IE edge 中曾经能够间接应用了,然而 chrome 和 Node.js 还没有反对。侥幸的是,babel 曾经反对 async 的 transform 了,所以咱们应用的时候引入 babel 就行。在开始之前咱们须要引入以下的 package,preset-stage- 3 里就有咱们须要的 async/await 的编译文件。
5.es6 中的 Module
ES6 中模块化语法更加简洁,应用 export 抛出,应用 import from 接管,
如果只是输入一个惟一的对象,应用 export default 即可
// 创立 util1.js 文件,内容如
export default {
a: 100
}
// 创立 index.js 文件,内容如
import obj from ‘./util1.js’
如果想要输入许多个对象,就不能用 default 了,且 import 时候要加{…},代码如下
// 创立 util2.js 文件,内容如
export function fn1() {
alert('fn1')
}
export function fn2() {
alert('fn2')
}
// 创立 index.js 文件,内容如
import {fn1, fn2} from ‘./util2.js’
6.ES6 class 和一般构造函数的区别
class 其实始终是 JS 的关键字(保留字),然而始终没有正式应用,直到 ES6。ES6 的 class 就是取代之前构造函数初始化对象的模式,从语法上更加合乎面向对象的写法
1)class 是一种新的语法模式,是 class Name {…} 这种模式,和函数的写法齐全不一样
2)两者比照,构造函数函数体的内容要放在 class 中的 constructor 函数中,constructor 即结构器,初始化实例时默认执行
3)class 中函数的写法是 add() {…}这种模式,并没有 function 关键字
而且应用 class 来实现继承就更加简略了
在 class 中间接 extends 关键字就能够实现继承,而不像之前的继承实现有多种不同的实现形式,在 es6 中就只有一种
留神以下两点:
应用 extends 即可实现继承,更加合乎经典面向对象语言的写法,如 Java
子类的 constructor 肯定要执行 super(),以调用父类的 constructor
7.ES6 中新增的数据类型有哪些?
Set 和 Map 都是 ES6 中新增的数据结构,是对以后 JS 数组和对象这两种重要数据结构的扩大。因为是新增的数据结构
1)Set 相似于数组,但数组能够容许元素反复,Set 不容许元素反复
2)Map 相似于对象,但一般对象的 key 必须是字符串或者数字,而 Map 的 key 能够是任何数据类型
8. 箭头函数的作用域上下文和 一般函数作用域上下文 的区别
箭头函数其实只是一个密名函数的语法糖,区别在于一般函数作用域中的 this 有特定的指向,个别指向 window,而箭头函数中的 this 只有一个指向那就是指以后函数所在的对象,其实现原理其实就是相似于之前编程的时候在函数外围定义 that 一样,用了箭头函数就不必定义 that 了间接应用 this
9.es6 如何转为 es5?
应用 Babel 转码器,Babel 的配置文件是.babelrc,寄存在我的项目的根目录下。应用 Babel 的第一步,就是配置这个文件。
算法
1. 浅拷贝 vs 深拷贝
拷贝其实就是对象复制,为了解决对象复制是产生的援用类型问题
浅拷贝:利用迭代器,循环对象将对象中的所有可枚举属性复制到另一个对象上,然而浅拷贝的有一个问题就是只是拷贝了对象的一级,其余级还如果是援用类型的值的话仍旧解决不了
深拷贝:深拷贝解决了浅拷贝的问题,利用递归的局势便当对象的每一级,实现起来较为简单,得判断值是数组还是对象,简略的说就是,在内存中存在两个数据结构完全相同又互相独立的数据,将援用型类型进行复制,而不是只复制其援用关系。
2. 常见的几种数组排序算法 JS 实现
1)疾速排序
从给定的数据中,随机抽出一项,这项的右边放所有比它小的,左边放比它大的,而后再别离这两边执行上述操作,采纳的是递归的思维,总结进去就是 实现一层,别离给两边递归,设置好进口
function fastSort(array,head,tail){
// 思考到给每个分区操作的时候都是在原有的数组中进行操作的,所以这里 head,tail 来确定分片的地位
/生成随机项 /
var randomnum = Math.floor(ranDom(head,tail));
var random = array[randomnum];
/ 将小于 random 的项搁置在其右边 策略就是通过一个长期的数组来贮存分好区的后果,再到原数组中替换/
var arrayTemp = [];
var unshiftHead = 0;
for(var i = head;i <= tail;i++){
if(array[i]<random){arrayTemp.unshift(array[i]);
unshiftHead++;
}else if(array[i]>random){arrayTemp.push(array[i]);
}
/* 当它等于的时候放哪,这里我想抉择放到队列的后面,也就是从 unshift 后的第一个地位搁置 */
if(array[i]===random){arrayTemp.splice(unshiftHead,0,array[i]);
}
}
/将对应项笼罩原来的记录/
for(var j = head , u=0;j <= tail;j++,u++){
array.splice(j,1,arrayTemp[u]);
}
/寻找两头项所在的 index/
var nowIndex = array.indexOf(random);
/设置进口,当要放进去的片段只有 2 项的时候就能够出工了/
if(arrayTemp.length <= 2){
return;
}
/递归,同时利用其左右两个区域 /
fastSort(array,head,nowIndex);
fastSort(array,nowIndex+1,tail);
}
2)插入排序
思维就是在曾经排好序的数组中插入到相应的地位,以从小到大排序为例,扫描曾经排好序的片段的每一项,如大于,则持续往后,直到他小于一项时,将其插入到这项的后面
function insertSort(array){
/start 依据已排列好的项数决定 /
var start=1;
/ 按程序,每一项查看已排列好的序列/
for(var i=start; i<array.length; start++,i++){
/* 跟已排好序的序列做比照,并插入到适合的地位 */
for(var j=0; j<start; j++){
/* 小于或者等于时(咱们是升序)插入到该项后面 */
if(array[i]<=array[j]){console.log(array[i]+' '+array[j]);
array.splice(j,0,array[i]);
/* 删除原有项 */
array.splice(i+1,1);
break;
}
}
}
}
3)冒泡排序
故名思意,就是一个个冒泡到最前端或者最初端,次要是通过两两顺次比拟,以升序为例,如果前一项比后一项大则替换程序,始终比到最初一对
function bubbleSort(array){
/给每个未确定的地位做循环/
for(var unfix=array.length-1; unfix>0; unfix–){
/* 给进度做个记录,比到未确定地位 */
for(var i=0; i<unfix;i++){if(array[i]>array[i+1]){var temp = array[i];
array.splice(i,1,array[i+1]);
array.splice(i+1,1,temp);
}
}
}
}
4)抉择排序
将以后未确定块的 min 或者 max 取出来插到最后面或者前面
function selectSort(array){
/* 给每个插入后的未确定的范畴循环,初始是从 0 开始 */
for(var unfixed=0; unfixed<array.length; unfixed++){
/* 设置以后范畴的最小值和其索引 */
var min = array[unfixed];
var minIndex = unfixed;
/* 在该范畴内选出最小值 */
for(var j=unfixed+1; j<array.length; j++){if(min>array[j]){min = array[j];
minIndex = j;
}
}
/* 将最小值插入到 unfixed,并且把它所在的原有项替换成 */
array.splice(unfixed,0,min);
array.splice(minIndex+1,1);
}
}
3. 写一个数组去重的办法
/** 办法一:
- 1. 构建一个新的数组寄存后果
- 2.for 循环中每次从原数组中取出一个元素,用这个元素循环与后果数组比照
- 3. 若后果数组中没有该元素,则存到后果数组中
- 缺点:不能去重数组中得援用类型的值和 NaN
*/
function unique(array){
var result = [];
for(var i = 0;i < array.length; i++){
if(result.indexOf(array[i]) == -1) {result.push(array[i]);
}
}
return result;
}
// [1,2,1,2,’1′,’2′,0,’1′,’ 你好 ’,’1′,’ 你好 ’,NaN,NaN] => [1, 2, “1”, “2”, 0, “ 你好 ”,NaN,NaN]
// [{id: ‘1’}, {id: ‘1’}] => [{id: ‘1’}, {id: ‘1’}]
// 办法二:ES6
Array.from(new Set(array))
// [1,2,1,2,’1′,’2′,0,’1′,’ 你好 ’,’1′,’ 你好 ’,NaN,NaN] => [1, 2, “1”, “2”, 0, “ 你好 ”, NaN]
4. 说一下 js 模板引擎
模板引擎原理总结起来就是:先获取 html 中对应的 id 下得 innerHTML,利用开始标签和敞开标签进行字符串切分,其实是将模板划分成两部份内容,一部分是 html 局部,一部分是逻辑局部,通过区别一些特殊符号比方 each、if 等来将字符串拼接成函数式的字符串, 将两局部各自通过解决后,再次拼接到一起,最初将拼接好的字符串采纳 new Function()的形式转化成所须要的函数。
罕用的模版引擎次要有,Template.js,handlebars.js
5. 是否理解公钥加密和私钥加密。
个别状况下是指私钥用于对数据进行签名,公钥用于对签名进行验证;
HTTP 网站在浏览器端用公钥加密敏感数据,而后在服务器端再用私钥解密。
6.js 深度复制的形式
1)应用 jq 的 $.extend(true, target, obj)
2)newobj = Object.create(sourceObj),// 然而这个是有个问题就是 newobj 的更改不会影响到 sourceobj 然而 sourceobj 的更改会影响到 newObj
3)newobj = JSON.parse(JSON.stringify(sourceObj))
7.js 设计模式
总体来说设计模式分为三大类:
创立型模式,共五种:工厂办法模式、形象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装璜器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板办法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模
具体:详情
http://www.alloyteam.com/2012…
8. 图片懒加载与预加载?
1)图片懒加载的原理就是临时不设置图片的 src 属性,而是将图片的 url 暗藏起来,比方先写在 data-src 外面,等某些事件触发的时候 (比方滚动到底部,点击加载图片) 再将图片实在的 url 放进 src 属性外面,从而实现图片的提早加载
Javascript 预加载图片的形式:
function preloadImg(url) {
var img = new Image();
img.src = url;
if(img.complete) {
// 接下来能够应用图片了
//do something here
} else {img.onload = function() {
// 接下来能够应用图片了
//do something here
};
}
}
2)图片预加载,是指在一些须要展现大量图片的网站,实现图片的提前加载。从而晋升用户体验。罕用的形式有两种,一种是暗藏在 css 的 background 的 url 属性外面,一种是通过 javascript 的 Image 对象设置实例对象的 src 属性实现图片的预加载。
CSS 预加载图片形式:
preload-01 {background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
preload-02 {background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
preload-03 {background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
9. 统计字符串中次数最多字母
function findMaxDuplicateChar(str) {
if(str.length == 1) {
return str;
}
var charObj = {};
for(var i = 0; i < str.length; i++) {
if(!charObj[str.charAt(i)]) {charObj[str.charAt(i)] = 1;
} else {charObj[str.charAt(i)] += 1;
}
}
var maxChar = ”,
maxValue = 1;
for(var k in charObj) {
if(charObj[k] >= maxValue) {
maxChar = k;
maxValue = charObj[k];
}
}
return maxChar + ‘:’ + maxValue;
}
19. 变态题目解析
https://juejin.im/entry/58ada…
11. 对 Node 的长处和毛病提出了本人的认识?
(长处)因为 Node 是基于事件驱动和无阻塞的,所以非常适合解决并发申请,因而构建在 Node 上的代理服务器相比其余技术实现(如 Ruby)的服务器体现要好得多。此外,与 Node 代理服务器交互的客户端代码是由 javascript 语言编写的,因而客户端和服务器端都用同一种语言编写,这是十分美好的事件。
(毛病)Node 是一个绝对新的开源我的项目,所以不太稳固,它总是始终在变,而且短少足够多的第三方库反对。看起来,就像是 Ruby/Rails 当年的样子。
模块化
1.commonjs?requirejs?AMD|CMD|UMD?
1)CommonJS 就是为 JS 的体现来制订标准,NodeJS 是这种标准的实现,webpack 也是以 CommonJS 的模式来书写。因为 js 没有模块的性能,所以 CommonJS 应运而生。但它不能在浏览器中运行。CommonJS 定义的模块分为:{模块援用(require)} {模块定义(exports)} {模块标识(module)}
2)RequireJS 是一个 JavaScript 模块加载器。RequireJS 有两个次要办法 (method): define() 和 require()。这两个办法基本上领有雷同的定义 (declaration) 并且它们都晓得如何加载的依赖关系,而后执行一个回调函数(callback function)。与 require() 不同的是,define()用来存储代码作为一个已命名的模块。因而 define()的回调函数须要有一个返回值作为这个模块定义。这些相似被定义的模块叫作 AMD (Asynchronous Module Definition,异步模块定义)。
3)AMD 是 RequireJS 在推广过程中对模块定义的规范化产出 AMD 异步加载模块。它的模块反对对象 函数 结构器 字符串 JSON 等各种类型的模块。实用 AMD 标准实用 define 办法定义模块。
4)CMD 是 SeaJS 在推广过程中对模块定义的规范化产出
AMD 与 CDM 的区别:
(1)对于于依赖的模块,AMD 是提前执行(如同当初也能够提早执行了),CMD 是提早执行。
(2)AMD 推崇依赖前置,CMD 推崇依赖就近。
(3)AMD 推崇复用接口,CMD 推崇单用接口。
(4)书写标准的差别。
5)umd 是 AMD 和 CommonJS 的糅合。
AMD 浏览器第一的准则倒退 异步加载模块。
CommonJS 模块以服务器第一准则倒退,抉择同步加载,它的模块无需包装(unwrapped modules)。这迫使人们又想出另一个更通用的模式 UMD (Universal Module Definition), 心愿解决跨平台的解决方案。UMD 先判断是否反对 Node.js 的模块(exports) 是否存在,存在则应用 Node.js 模块模式。
2. 模块化的了解
模块化的话其实次要就是对于 js 性能逻辑的划分,在 js 中咱们个别都吧一个 js 文件定义成一个模块,模块次要的职责就是(封装实现,裸露接口,申明依赖)
3.AMD 和 CMD 的区别
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
对于依赖的模块,AMD 是提前执行,CMD 是提早执行。不过 RequireJS 从 2.0 开始,也改成能够提早执行(依据写法不同,解决形式不同)。CMD 推崇 as lazy as possible.
CMD 推崇依赖就近,AMD 推崇依赖前置。
AMD 的 API 默认是一个当多个用,CMD 的 API 严格辨别,推崇职责繁多。比方 AMD 里,require 分全局 require 和部分 require,都叫 require。CMD 里,没有全局 require,而是依据模块零碎的齐备性,提供 seajs.use 来实现模块零碎的加载启动。CMD 里,每个 API 都简略纯正。
前端平安
1.XSS(Cross Site Scripting,跨站脚本攻打)
这是前端最常见的攻击方式,很多大型网站(如 Facebook)都被 XSS 攻打过。
举一个例子,我在一个博客网站失常发表一篇文章,输出汉字、英文和图片,齐全没有问题。然而如果我写的是歹意的 JS 脚本,例如获取到 document.cookie 而后传输到本人的服务器上,那我这篇博客的每一次浏览都会执行这个脚本,都会把访客 cookie 中的信息偷偷传递到我的服务器上来。
其实原理上就是黑客通过某种形式(公布文章、公布评论等)将一段特定的 JS 代码荫蔽地输出进去。而后他人再看这篇文章或者评论时,之前注入的这段 JS 代码就执行了。JS 代码一旦执行,那可就不受管制了,因为它跟网页原有的 JS 有同样的权限,例如能够获取 server 端数据、能够获取 cookie 等。于是,攻打就这样产生了。
XSS 的危害
XSS 的危害相当大,如果页面能够随便执行他人不平安的 JS 代码,轻则会让页面错乱、性能缺失,重则会造成用户的信息泄露。
比方早些年社交网站常常爆出 XSS 蠕虫,通过公布的文章内插入 JS,用户拜访了感化不平安 JS 注入的文章,会主动从新公布新的文章,这样的文章会通过举荐零碎进入到每个用户的文章列表背后,很快就会造成大规模的感化。
还有利用获取 cookie 的形式,将 cookie 传入入侵者的服务器上,入侵者就能够模仿 cookie 登录网站,对用户的信息进行篡改。
XSS 的预防
那么如何预防 XSS 攻打呢?—— 最基本的形式,就是对用户输出的内容进行验证和替换,须要替换的字符有:
& 替换为:&
< 替换为:<
替换为:>
”替换为:”
‘替换为:’
/ 替换为:/
替换了这些字符之后,黑客输出的攻打代码就会生效,XSS 攻打将不会轻易产生。
除此之外,还能够通过对 cookie 进行较强的管制,比方对敏感的 cookie 减少 http-only 限度,让 JS 获取不到 cookie 的内容。
2.CSRF(Cross-site request forgery,跨站申请伪造)
CSRF 是借用了以后操作者的权限来偷偷地实现某个操作,而不是拿到用户的信息。
例如,一个领取类网站,给别人转账的接口是 http://buy.com/pay?touid=999&…,而这个接口在应用时没有任何明码或者 token 的验证,只有关上拜访就间接给别人转账。一个用户曾经登录了 http://buy.com,在抉择商品时,忽然收到一封邮件,而这封邮件注释有这么一行代码,他拜访了邮件之后,其实就曾经实现了购买。
CSRF 的产生其实是借助了一个 cookie 的个性。咱们晓得,登录了 http://buy.com 之后,cookie 就会有登录过的标记了,此时申请 http://buy.com/pay?touid=999&… cookie 的,因而 server 端就晓得曾经登录了。而如果在 http://buy.com 去申请其余域名的 API 例如 http://abc.com/api 时,是不会带 cookie 的,这是浏览器的同源策略的限度。然而 —— 此时在其余域名的页面中,申请 http://buy.com/pay?touid=999&…,会带着 buy.com 的 cookie,这是产生 CSRF 攻打的实践根底。
预防 CSRF 就是退出各个层级的权限验证,例如当初的购物网站,只有波及现金交易,必定要输出明码或者指纹才行。除此之外,敏感的接口应用 POST 申请而不是 GET 也是很重要的。1.javaScript 的数据类型有什么
Undefined、Null、Boolean、Number、String
2. 检测数据类型有什么办法
typeof
typeof xxx 失去的值有以下几种类型:undefined boolean number string object function、symbol,比较简单,不再一一演示了。
这里须要留神的有三点:
- typeof null 后果是 object,理论这是 typeof 的一个 bug,null 是原始值,非援用类型
- typeof [1, 2]后果是 object,后果中没有 array 这一项,援用类型除了 function 其余的全部都是 object
- typeof Symbol() 用 typeof 获取 symbol 类型的值得到的是 symbol,这是 ES6 新增的知识点
instanceof
用于实例和构造函数的对应。例如判断一个变量是否是数组,应用 typeof 无奈判断,但能够应用 [1, 2] instanceof Array 来判断。因为,[1, 2] 是数组,它的构造函数就是 Array。同理:
function Foo(name) {this.name = name}
var foo = new Foo('bar’)
console.log(foo instanceof Foo) // true
3. 介绍 js 有哪些内置对象?
Object 是 JavaScript 中所有对象的父对象
数据封装类对象:Object、Array、Boolean、Number 和 String
其余对象:Function、Arguments、Math、Date、RegEx、Error
4. 如何辨别数组和对象?
(1)从原型动手,Array.prototype.isPrototypeOf(obj); 利用 isPrototypeOf()办法,断定 Array 是不是在 obj 的原型链中,如果是,则返回 true, 否则 false。Array.prototype.isPrototype([]) //true
(2)也能够从构造函数动手,利用对向的 constructor 属性
(3)依据对象的 class 属性(类属性),跨原型链调用 toString() 办法。Object.prototype.toString.call(Window);
(4)Array.isArray()办法。
5.null,undefined 的区别?
null 示意一个对象被定义了,值为“空值”;
undefined 示意不存在这个值。
typeof undefined //”undefined”
undefined : 是一个示意 ” 无 ” 的原始值或者说示意 ” 短少值 ”,就是此处应该有一个值,然而还没有定义。当尝试读取时会返回 undefined;
例如变量被申明了,但没有赋值时,就等于 undefined
typeof null //”object”
null : 是一个对象 (空对象, 没有任何属性和办法);
例如作为函数的参数,示意该函数的参数不是对象;
留神:
在验证 null 时,肯定要应用 ===,因为 == 无奈别离 null 和 undefined
undefined 示意 ” 短少值 ”,就是此处应该有一个值,然而还没有定义。典型用法是:
1)变量被申明了,但没有赋值时,就等于 undefined。
2) 调用函数时,应该提供的参数没有提供,该参数等于 undefined。
3)对象没有赋值的属性,该属性的值为 undefined。
4)函数没有返回值时,默认返回 undefined。
null 示意 ” 没有对象 ”,即该处不应该有值。
典型用法是:
1)作为函数的参数,示意该函数的参数不是对象。
2)作为对象原型链的起点。
6. 申明变量和申明函数的晋升有什么区别?
(1) 变量申明晋升:变量申明在进入执行上下文就实现了。
只有变量在代码中进行了申明,无论它在哪个地位上进行申明,js 引擎都会将它的申明放在范畴作用域的顶部;
(2) 函数申明晋升:执行代码之前会先读取函数申明,意味着能够把函数申明放在调用它的语句前面。
只有函数在代码中进行了申明,无论它在哪个地位上进行申明,js 引擎都会将它的申明放在范畴作用域的顶部;
(3) 变量 or 函数申明:函数申明会笼罩变量申明,但不会笼罩变量赋值。
同一个名称标识 a,即有变量申明 var a,又有函数申明 function a() {},不论二者申明的程序,函数申明会笼罩变量申明,也就是说,此时 a 的值是申明的函数 function a() {}。留神:如果在变量申明的同时初始化 a,或是之后对 a 进行赋值,此时 a 的值变量的值。eg: var a; var c = 1; a = 1; function a() { return true;} console.log(a);
原型,原型链
1.JavaScript 原型,原型链 ? 有什么特点?
原型
每个对象都会在其外部初始化一个属性,就是 prototype(原型)
应用 hasOwnProperty() 能够判断这个属性是不是对象自身的属性
问题:Javascript 中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
hasOwnProperty
javaScript 中 hasOwnProperty 函数办法是返回一个布尔值,指出一个对象是否具备指定名称的属性。此办法无奈查看该对象的原型链中是否具备该属性;该属性必须是对象自身的一个成员。
应用办法:
object.hasOwnProperty(proName)
其中参数 object 是必选项。一个对象的实例。
proName 是必选项。一个属性名称的字符串值。
如果 object 具备指定名称的属性,那么 JavaScript 中 hasOwnProperty 函数办法返回 true,反之则返回 false。
原型链
当咱们在拜访一个对象的属性时,如果这个对象外部不存在这个属性,那么他就会去 prototype 里找这个属性,这个 prototype 又会有本人的 prototype,于是就这样始终找上来,找到 Object.__proto__为止,找不到就返回 unde 也就是咱们平时所说的原型链的概念。
关系:instance.constructor.prototype = instance.__proto__
特点:
JavaScript 对象是通过援用来传递的,咱们创立的每个新对象实体中并没有一份属于本人的原型正本。当咱们批改原型时,与之相干的对象也会继承这一扭转。
当咱们须要一个属性的时,Javascript 引擎会先看以后对象中是否有这个属性,如果没有的话,就会查找他的 Prototype 对象是否有这个属性,如此递推上来,始终检索到 Object 内建对象。
所有的援用类型(数组、对象、函数),都具备对象个性,即可自在扩大属性(null 除外)
所有的援用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个一般的对象
所有的函数,都有一个 prototype 属性,属性值也是一个一般的对象
所有的援用类型(数组、对象、函数),__proto__属性值指向它的构造函数的 prototype 属性值
原型链中的 this
所有从原型或更高级原型中失去、执行的办法,其中的 this 在执行时,就指向了以后这个触发事件执行的对象。
闭包
闭包的造成与变量的作用域以及变量的生存周期有亲密的关系
1. 变量的作用域
- 在 js 中咱们把作用域分为全局作用域和部分作用域,全局作用域就是 window,在没有块级作用域概念的时候,每一个函数都是一个部分作用域。
- 其实变量的作用域,就说指变量的无效范畴。咱们最长说的就是在函数中申明的变量作用域。
- 当在函数中申明一个变量的时候,如果扭转量没有用 var 关键字去定义那么该变量就是一个全局变量,然而这样做最容易造成命名抵触。
- 另一种状况就是应用 var 申明的变量,这时候的变量就是局部变量,只有在该函数外部能够拜访,在函数里面是拜访不到的
- 在 javascript 中,函数能够用来发明函数作用域。在函数中搜寻变量的时候,如果该函数当中没有这个变量,那么这次搜寻过程会随着代码执行环境创立的作用域链往外层逐层搜寻,始终搜寻到 window 对象为止,找不到就会抛出一个为定义的谬误。而这种从内到外逐层查找的关系在 js 中咱们称为作用域链
2. 变量的生存周期
除了变量作用域之外,另外一个跟闭包无关的概念就是变量的生存周期,对于全局变量来说,全局变量的生存周期是永恒的,除非咱们被动销毁这个全局变量,而对于函数外部的应用 var 申明的变量来说,当退出函数是,这些变量就会随着函数的完结而销毁。
3. 闭包的造成
Javascript 容许应用外部函数,能够将函数定义和函数表达式放在另一个函数的函数体内。而且,外部函数能够拜访它所在的内部函数申明的局部变量、参数以及申明的其余外部函数。当其中一个这样的外部函数在蕴含它们的内部函数之外被调用时,就会造成闭包。常见的闭包写法就是简略的函数套函数,通过另一个函数拜访这个函数的局部变量, 利用闭包能够冲破作用域链,将函数外部的变量和办法传递到内部,连续变量的生命。应用闭包能够缩小全局环境的净化,也可用连续变量的生命。
4. 闭包的实用场景
闭包的实用场景十分宽泛,首先从闭包的长处登程就是:
缩小全局环境的净化生成独立的运行环境
模块化就是利用这个特点对不同的模块都有本人独立的运行环境,不会和全局抵触,模块和模块之间通过抛出的接口进行依赖应用
以及像咱们罕用的 jquery 类库(防止和全局抵触应用闭包实现本人独立的环境)
能够通过返回其余函数的形式冲破作用域链
能够利用这个性能做一些值的缓存工作,例如常见的设计模式(单例模式),以及当初比拟火的框架 vue 中的计算属性
其实当遇到以下场景的时候都能够应用闭包
1) 保护函数内的变量平安, 防止全局变量的净化。
2) 维持一个变量不被回收。
3) 封装模块
5. 闭包的毛病
因为闭包会使得函数中的变量都被保留在内存中,内存耗费很大。所以在闭包不必之后,将不应用的局部变量删除,使其被回收。在 IE 中可能导致内存泄露,即无奈回收驻留在内存中的元素,这时候须要手动开释。
6. 内存泄露
内存透露指一块被调配的内存既不能应用,又不能回收,直到浏览器过程完结。
呈现起因:
1) 循环援用:含有 DOM 对象的循环援用将导致大部分以后支流浏览器内存泄露。循环 援用,简略来说如果 a 援用了 b,b 又援用了 a,a 和 b 就形成了循环援用。
2) JS 闭包:闭包,函数返回了外部函数还能够持续拜访内部办法中定义的公有变量。
3) Dom 泄露,当原有的 DOM 被移除时,子结点援用没有被移除则无奈回收。
7.JavaScript 垃圾回收机制
Javascript 中,如果一个对象不再被援用,那么这个对象就会被 GC(garbage collection)回收。如果两个对象相互援用,而不再被第 3 者所援用,那么这两个相互援用的对象也会被回收。垃圾回收不是时时的,因为其开销比拟大,所以垃圾回收器会依照固定的工夫距离周期性的执行。
函数 a 被 b 援用,b 又被 a 外的 c 援用,这就是为什么函数 a 执行后不会被回收的起因。
8. 垃圾回收的两个办法:
标记革除法:
1) 垃圾回收机制给存储在内存中的所有变量加上标记,而后去掉环境中的变量以及被环境中变量所援用的变量(闭包)。
2) 操作 1 之后内存中仍存在标记的变量就是要删除的变量,垃圾回收机制将这些带有标记的变量回收。
援用计数法:
1) 垃圾回收机制给一个变量一个援用次数,当申明了一个变量并将一个援用类型赋值给该变量的时候这个值的援用次数就加 1。
2) 当该变量的值变成了另外一个值,则这个值得引用次数减 1。
3) 当这个值的援用次数变为 0 的时候,阐明没有变量在应用,垃圾回收机制会在运行的时候清理掉援用次数为 0 的值占用的空间。
JS 运行机制
JavaScript 引擎是单线程运行的, 浏览器无论在什么时候都只且只有一个线程在运行 JavaScript 程序. 浏览器的内核是多线程的,它们在内核制控下相互配合以放弃同步,一个浏览器至多实现三个常驻线程:javascript 引擎线程,GUI 渲染线程,浏览器事件触发线程。这些异步线程都会产生不同的异步的事件.
1) javascript 引擎是基于事件驱动单线程执行的,JS 引擎始终期待着工作队列中工作的到来,而后加以解决,浏览器无论什么时候都只有一个 JS 线程在运行 JS 程序。
2) GUI 渲染线程负责渲染浏览器界面,当界面须要重绘(Repaint)或因为某种操作引发回流 (reflow) 时, 该线程就会执行。但须要留神 GUI 渲染线程与 JS 引擎是互斥的,当 JS 引擎执行时 GUI 线程会被挂起,GUI 更新会被保留在一个队列中等到 JS 引擎闲暇时立刻被执行。
3) 事件触发线程,当一个事件被触发时该线程会把事件增加到待处理队列的队尾,期待 JS 引擎的解决。这些事件可来自 JavaScript 引擎以后执行的代码块如 setTimeOut、也可来自浏览器内核的其余线程如鼠标点击、AJAX 异步申请等,但因为 JS 的单线程关系所有这些事件都得排队期待 JS 引擎解决。(当线程中没有执行任何同步代码的前提下才会执行异步代码)
当程序启动时, 一个过程被创立,同时也运行一个线程, 即为主线程,js 的运行机制为单线程
程序中跑两个线程,一个负责程序自身的运行,作为主线程;另一个负责主线程与其余线程的的通信,被称为“Event Loop 线程 ”。每当遇到异步工作,交给 EventLoop 线程,而后本人往后运行,等到主线程运行完后,再去 EventLoop 线程拿后果。
1)所有工作都在主线程上执行,造成一个执行栈(execution context stack)。
2)主线程之外,还存在一个 ” 工作队列 ”(task queue)。零碎把异步工作放到 ” 工作队列 ” 之中,而后继续执行后续的工作。
3)一旦 ” 执行栈 ” 中的所有工作执行结束,零碎就会读取 ” 工作队列 ”。如果这个时候,异步工作曾经完结了期待状态,就会从 ” 工作队列 ” 进入执行栈,复原执行。
4)主线程一直反复下面的第三步。
“ 回调函数 ”(callback),就是那些会被主线程挂起来的代码。异步工作必须指定回调函数,当异步工作从 ” 工作队列 ” 回到执行栈,回调函数就会执行。” 工作队列 ” 是一个先进先出的数据结构,排在后面的事件,优先返回主线程。主线程的读取过程基本上是主动的,只有执行栈一清空,” 工作队列 ” 上第一位的事件就主动返回主线程。
主线程从 ” 工作队列 ” 中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为 Event Loop。
从主线程的角度看,一个异步过程包含上面两个因素:
发动函数 (或叫注册函数)A
回调函数 callbackFn
它们都是在主线程上调用的,其中注册函数用来发动异步过程,回调函数用来处理结果。
异步过程有:
相似 onclick 等,由浏览器内核的 DOM binding 模块解决,事件触发时,回调函数增加到工作队列中;
setTimeout 等,由浏览器内核的 Timer 模块解决,工夫达到时,回调函数增加到工作队列中;
Ajax,由浏览器内核的 Network 模块解决,网络申请返回后,增加到工作队列中。
例如 setTimeout(fn, 1000),其中的 setTimeout 就是异步过程的发动函数,fn 是回调函数。用一句话概括:工作线程将音讯放到音讯队列,主线程通过事件循环过程去取音讯。
音讯队列:音讯队列是一个先进先出的队列,它外面寄存着各种音讯。
事件循环:事件循环是指主线程反复从音讯队列中取音讯、执行的过程。
流程如下:
1) 主线程读取 js 代码, 造成相应的堆和执行栈, 执行同步工作
2) 当主线程遇到异步工作,,指定给异步过程解决, 同时继续执行同步工作
3) 当异步过程处理完毕后,将相应的异步工作推入到工作队列首部
4) 主线程工作处理完毕后,,查问工作队列,则取出一个工作队列推入到主线程的执行栈
5) 反复执行第 2、3、4 步,这就称为事件循环
JS-Web-API 知识点与高频考题解析
BOM
BOM(浏览器对象模型)是浏览器自身的一些信息的设置和获取,例如获取浏览器的宽度、高度,设置让浏览器跳转到哪个地址。
navigator:获取浏览器个性(即俗称的 UA)而后辨认客户端
location:获取网址、协定、path、参数、hash 等
history:操作浏览器的历史纪录,(后退,后退等性能)
1. 什么是 window 对象? 什么是 document 对象?
window: 它是一个顶层对象, 而不是另一个对象的属性,即浏览器的窗口。
document: 代表整个 HTML 文档, 可用来拜访页面中的所有元素
Window 对象示意以后浏览器的窗口,是 JavaScript 的顶级对象。咱们创立的所有对象、函数、变量都是 Window 对象的成员。
Window 对象的办法和属性是在全局范畴内无效的。
Document 对象是 HTML 文档的根节点与所有其余节点(元素节点,文本节点,属性节点, 正文节点)
Document 对象使咱们能够通过脚本对 HTML 页面中的所有元素进行拜访
Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行拜访
2. 事件是?IE 与火狐的事件机制有什么区别?如何阻止冒泡?
1) 咱们在网页中的某个操作(有的操作对应多个事件)。例如:当咱们点击一个按钮就会产生一个事件。是能够被 JavaScript 侦测到的行为。
2) 事件处理机制:IE 是事件冒泡、Firefox 同时反对两种事件模型,也就是:捕捉型事件和冒泡型事件;
3) ev.stopPropagation();(旧 ie 的办法 ev.cancelBubble = true;)
3. 解释一下事件代理
事件代理的原理其实就和作用域链的原理差不多,然而事件代理是利用事件的冒泡原理来实现的,事件代理就是通过给先人元素增加事件,通过事件指标对象开始向上查找找到匹配的子节点为止,如果找不到则到绑定事件的那个先人元素为止,找到了就触发事件,并且能够通过 js 中 call 和 apply 来扭转触发事件函数中的 this 为以后绑定节点,也是通过一层一层逐层向上的形式进行匹配查找而触发对应事件,益处就是能够使后增加的 dom 元素也同样有之前存在元素的事件,jquery 中能够应用 on,delegate,live 实现的,不过在 jquery1.7 版本当前吧 live 给破除了,起因就是 live 绑定事件的先人元素是整个 html 页面的根节点,所以性能耗费比拟大,在后边的版本中给删除了,应用 on,delegate 代替
长处:
使代码简洁
缩小浏览器的内存占用
毛病:
使用不当会造成事件在不应该触发时触发
function bindEvent(elem, type, selector, fn) {// 这样解决,可接管两种调用形式 bindEvent(div1, 'click', 'a', function () {...}) 和 bindEvent(div1, 'click', function () {...}) 这两种
if (fn == null) {
fn = selector
selector = null
}
// 绑定事件
elem.addEventListener(type, function (e) {
var target
if (selector) {
// 有 selector 阐明须要做事件代理
// 获取触发工夫的元素,即 e.target
target = e.target
// 看是否合乎 selector 这个条件
if (target.matches(selector)) {fn.call(target, e)
}
} else {
// 无 selector,阐明不须要事件代理
fn(e)
}
})
}
// 应用代理,bindEvent 多一个 'a' 参数
var div1 = document.getElementById('div1')
bindEvent(div1, 'click', 'a', function (e) {console.log(this.innerHTML)
})
// 不应用代理
var a = document.getElementById('a1')
bindEvent(div1, 'click', function (e) {console.log(a.innerHTML)
})
4.offsetWidth/offsetHeight,clientWidth/clientHeight 与 scrollWidth/scrollHeight 的区别
offsetWidth/offsetHeight 返回值蕴含 content + padding + border,成果与 e.getBoundingClientRect()雷同
clientWidth/clientHeight 返回值只蕴含 content + padding,如果有滚动条,也不蕴含滚动条
scrollWidth/scrollHeight 返回值蕴含 content + padding + 溢出内容的尺寸
5.focus/blur 与 focusin/focusout 的区别与分割
focus/blur 不冒泡,focusin/focusout 冒泡
focus/blur 兼容性好,focusin/focusout 在除 FireFox 外的浏览器下都保持良好兼容性,如需应用事件托管,可思考在 FireFox 下应用事件捕捉 elem.addEventListener(‘focus’, handler, true)
可取得焦点的元素:
window
链接被点击或键盘操作
表单空间被点击或键盘操作
设置 tabindex 属性的元素被点击或键盘操作
6.mouseover/mouseout 与 mouseenter/mouseleave 的区别与分割
mouseover/mouseout 是规范事件,所有浏览器都反对;mouseenter/mouseleave 是 IE5.5 引入的特有事件起初被 DOM3 规范驳回,古代规范浏览器也反对
mouseover/mouseout 是冒泡事件;mouseenter/mouseleave 不冒泡。须要为多个元素监听鼠标移入 / 出事件时,举荐 mouseover/mouseout 托管,进步性能
规范事件模型中 event.target 示意产生移入 / 出的元素,vent.relatedTarget 对应移出 / 如元素;在老 IE 中 event.srcElement 示意产生移入 / 出的元素,event.toElement 示意移出的指标元素,event.fromElement 示意移入时的起源元素
7. 介绍 DOM0,DOM2,DOM3 事件处理形式区别
DOM0 级事件处理形式:
btn.onclick = func;
btn.onclick = null;
DOM2 级事件处理形式:
btn.addEventListener('click', func, false);
btn.removeEventListener('click', func, false);
btn.attachEvent("onclick", func);
btn.detachEvent("onclick", func);
DOM3 级事件处理形式:
eventUtil.addListener(input, “textInput”, func);
eventUtil 是自定义对象,textInput 是 DOM3 级事件
8. 事件的三个阶段
捕捉、指标、冒泡
js 的冒泡 (Bubbling Event) 和捕捉 (Capture Event) 的区别
冒泡型事件:事件依照从最特定的事件指标到最不特定的事件指标 (document 对象) 的程序触发。
捕捉型事件 (event capturing): 事件从最不准确的对象 (document 对象) 开始触发,而后到最准确 (也能够在窗口级别捕捉事件,不过必须由开发人员特地指定)。
DOM 事件流: 同时反对两种事件模型:捕捉型事件和冒泡型事件,然而,捕捉型事件先产生。两种事件流会涉及 DOM 中的所有对象,从 document 对象开始,也在 document 对象完结。
事件捕捉
当你应用事件捕捉时,父级元素先触发,子级元素后触发,即 div 先触发,p 后触发。
事件冒泡
当你应用事件冒泡时,子级元素先触发,父级元素后触发,即 p 先触发,div 后触发。
阻止冒泡
- 在 W3c 中,应用 stopPropagation()办法
- 在 IE 下设置 cancelBubble = true;
在捕捉的过程中 stopPropagation();后,前面的冒泡过程也不会产生了。
阻止捕捉
阻止事件的默认行为,例如 click 后的跳转
- 在 W3c 中,应用 preventDefault()办法;
- 在 IE 下设置 window.event.returnValue = false;
9. 介绍事件“捕捉”和“冒泡”执行程序和事件的执行次数?
依照 W3C 规范的事件:首是进入捕捉阶段,直到达到目标元素,再进入冒泡阶段
事件执行次数(DOM2-addEventListener):元素上绑定事件的个数
留神 1:前提是事件被的确触发
留神 2:事件绑定几次就算几个事件,即便类型和性能齐全一样也不会“笼罩”
事件执行程序:判断的要害是否指标元素
非指标元素:依据 W3C 的规范执行:捕捉 -> 指标元素 -> 冒泡(不根据事件绑定程序)
指标元素:根据事件绑定程序:先绑定的事件先执行(不根据捕捉冒泡规范)
最终程序:父元素捕捉 -> 指标元素事件 1 -> 指标元素事件 2 -> 子元素捕捉 -> 子元素冒泡 -> 父元素冒泡
留神:子元素事件执行前提 事件的确“落”到子元素布局区域上,而不是简略的具备嵌套关系
在一个 DOM 上同时绑定两个点击事件:一个用捕捉,一个用冒泡。事件会执行几次,先执行冒泡还是捕捉?
该 DOM 上的事件如果被触发,会执行两次(执行次数等于绑定次数)
如果该 DOM 是指标元素,则按事件绑定程序执行,不辨别冒泡 / 捕捉
如果该 DOM 是处于事件流中的非指标元素,则先执行捕捉,后执行冒泡
10.window.onload 和 document.DOMContentLoaded (注:$(document).ready()) 的区别?
个别状况下,DOMContentLoaded 事件要在 window.onload 之前执行,当 DOM 树构建实现的时候就会执行 DOMContentLoaded 事件,而 window.onload 是在页面载入实现的时候,才执行,这其中包含图片等元素。大多数时候咱们只是想在 DOM 树构建实现后,绑定事件到元素,咱们并不需要图片元素,加上有时候加载外域图片的速度十分迟缓。
DOM
讲 DOM 先从 HTML 讲起,讲 HTML 先从 XML 讲起。XML 是一种可扩大的标记语言,所谓可扩大就是它能够形容任何结构化的数据,它是一棵树!
1.documen.write 和 innerHTML 的区别
document.write 只能重绘整个页面
innerHTML 能够重绘页面的一部分
2.DOM 操作——怎么增加、移除、挪动、复制、创立和查找节点?
1)创立新节点
createDocumentFragment() // 创立一个 DOM 片段
createElement() // 创立一个具体的元素
createTextNode() // 创立一个文本节点
2)增加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() // 在已有的子节点前插入一个新的子节点
3)查找
getElementsByTagName() // 通过标签名称
getElementsByName() // 通过元素的 Name 属性的值(IE 容错能力较强,会失去一个数组,其中包含 id 等于 name 值的)
getElementById() // 通过元素 Id,唯一性
3.attribute 和 property 的区别是什么?
attribute 是 dom 元素在文档中作为 html 标签领有的属性;
property 就是 dom 元素在 js 中作为对象领有的属性。
所以:
对于 html 的规范属性来说,attribute 和 property 是同步的,是会自动更新的,
然而对于自定义的属性来说,他们是不同步的,
4.src 和 href 的区别
src 用于替换以后元素,href 用于在以后文档和援用资源之间确立分割。
src 是 source 的缩写,指向内部资源的地位,指向的内容将会嵌入到文档中以后标签所在位置;在申请 src 资源时会将其指向的资源下载并利用到文档内,当浏览器解析到该元素时,会暂停其余资源的下载和解决,直到将该资源加载、编译、执行结束,图片和框架等元素也如此,相似于将所指向资源嵌入以后标签内。这也是为什么将 js 脚本放在底部而不是头部。
Src source, 指向内部资源的地位, 如果咱们增加 <script src =”js.js”></script> 浏览器会暂停其余资源的下载和解决, 直到该资源加载, 编译, 执行结束(图片和框架也是如此), 这也就是为什么 js 脚本要放在底部。
src 用于替换以后元素,href 用于在以后文档和引入资源之间建立联系。
对象
1,JavaScript 继承的几种实现形式?
1)构造函数继承,应用 call 和 apply 两个办法的个性能够实现,扭转办法中的 this
2)原型链继承
3)组合式继承
2.javascript 创建对象的几种形式?
javascript 创建对象简略的说, 无非就是应用内置对象或各种自定义对象,当然还能够用 JSON;但写法有很多种,也能混合应用。
1) 对象字面量的形式 person={firstname:”Mark”,lastname:”Yun”,age:25,eyecolor:”black”};
2) 用 function 来模仿无参的构造函数
function Person(){}
var person=new Person();// 定义一个 function,如果应用 new” 实例化 ”, 该 function 能够看作是一个 Class
person.name=“Mark”;
person.age=”25″;
person.work=function(){
alert(person.name+” hello…”);
}
person.work();
3) 用 function 来模仿参构造函数来实现(用 this 关键字定义结构的上下文属性)
function Pet(name,age,hobby){
this.name=name;//this 作用域:以后对象
this.age=age;
this.hobby=hobby;
this.eat=function(){
alert(“ 我叫 ”+this.name+”, 我喜爱 ”+this.hobby+”, 是个程序员 ”);
}
}
var maidou =new Pet(“ 麦兜 ”,25,”coding”);// 实例化、创建对象
maidou.eat();// 调用 eat 办法
4) 用工厂形式来创立(内置对象)
var wcDog =new Object();
wcDog.name="旺财";
wcDog.age=3;
wcDog.work=function(){alert("我是"+wcDog.name+", 汪汪汪......");
}
wcDog.work();
5、用原型形式来创立
function Dog(){}
Dog.prototype.name="旺财";
Dog.prototype.eat=function(){alert(this.name+"是个吃货");}
var wangcai =new Dog();
wangcai.eat();
5) 用混合形式来创立
function Car(name,price){
this.name=name;
this.price=price;
}
Car.prototype.sell=function(){alert("我是"+this.name+",我当初卖"+this.price+"万元");
}
var camry =new Car("凯美瑞",27);
camry.sell();
3. 谈谈 This 对象的了解。
this 分为几个不同的应用场景,在 function 中 this 指的的是 window,如果是实用 new 调用的话 this 指的是以后的实例化对象,在事件调用函数中 this 指的调用事件的 window 非凡的是在 IE 中的 attachEvent 中的 this 总是指向全局对象 Window;,在定时器中 this 指的是 window,在 es6 中有一个箭头函数,在箭头函数中 this 永远指向的是父级对象,this 也是能够扭转的,在 js 中 call, apply, bind 都能够扭转 this 的指向,call, apply 都是执行一个函数并且扭转 this,区别就是参数传递不一样,而 bind 是返回一个绑定 this 之后的新函数
4.javascript 代码中的 ”use strict”; 是什么意思 ? 应用它区别是什么?
use strict 是一种 ECMAscript 5 增加的(严格)运行模式, 这种模式使得 Javascript 在更严格的条件下运行,
使 JS 编码更加规范化的模式, 打消 Javascript 语法的一些不合理、不谨严之处,缩小一些怪异行为。
默认反对的蹩脚个性都会被禁用,比方不能用 with,也不能在意外的状况下给全局变量赋值;
全局变量的显示申明, 函数必须申明在顶层,不容许在非函数代码块内申明函数,arguments.callee 也不容许应用;
打消代码运行的一些不平安之处,保障代码运行的平安, 限度函数中的 arguments 批改,严格模式下的 eval 函数的行为和非严格模式的也不雷同;
进步编译器效率,减少运行速度;
为将来新版本的 Javascript 标准化做铺垫。
5.JSON 的理解?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格局。
它是基于 JavaScript 的一个子集。数据格式简略, 易于读写, 占用带宽小
如:{“age”:”12″, “name”:”back”}
JSON 字符串转换为 JSON 对象:
var obj =eval('('+ str +')');
var obj = str.parseJSON();
var obj = JSON.parse(str);
JSON 对象转换为 JSON 字符串:
var last=obj.toJSONString();
var last=JSON.stringify(obj);
6. .call() 和 .apply() 的区别?
7. 什么是函数节流?介绍一下利用场景和原理?
函数节流 (throttle) 是指阻止一个函数在很短时间距离内间断调用。只有当上一次函数执行后达到规定的工夫距离,能力进行下一次调用。但要保障一个累计最小调用距离(否则拖拽类的节流都将无间断成果)
函数节流用于 onresize, onscroll 等短时间内会屡次触发的事件
函数节流的原理:应用定时器做工夫节流。当触发一个事件时,先用 setTimout 让这个事件提早一小段时间再执行。如果在这个工夫距离内又触发了事件,就 clearTimeout 原来的定时器,再 setTimeout 一个新的定时器反复以上流程。
函数节流简略实现:
function throttle(method, context) {clearTimeout(methor.tId);
method.tId = setTimeout(function(){method.call(context);
},100); // 两次调用至多距离 100ms
}
// 调用
window.onresize = function(){throttle(myFunc, window);
}
8.new 操作符具体干了什么?
创立实例对象,this 变量援用该对象,同时还继承了构造函数的原型
属性和办法被退出到 this 援用的对象中
新创建的对象由 this 所援用,并且最初隐式的返回 this
new 共经验了四个过程。
var fn = function () {};
var fnObj = new fn();
1)创立了一个空对象
var obj = new object();
2)设置原型链
obj._proto_ = fn.prototype;
3)让 fn 的 this 指向 obj,并执行 fn 的函数体
var result = fn.call(obj);
4)判断 fn 的返回值类型,如果是值类型,返回 obj。如果是援用类型,就返回这个援用类型的对象。
if (typeof(result) == "object"){fnObj = result;} else {fnObj = obj;}
兼容与优化
1. 页面重构怎么操作?
网站重构:在不扭转内部行为的前提下,简化构造、增加可读性,而在网站前端保持一致的行为。
也就是说是在不扭转 UI 的状况下,对网站进行优化,在扩大的同时保持一致的 UI。
对于传统的网站来说重构通常是:
表格 (table) 布局改为 DIV+CSS
使网站前端兼容于古代浏览器 (针对于不合标准的 CSS、如对 IE6 无效的)
对于挪动平台的优化
针对于 SEO 进行优化
深层次的网站重构应该思考的方面
缩小代码间的耦合
让代码放弃弹性
严格按标准编写代码
设计可扩大的 API
代替旧有的框架、语言 (如 VB)
加强用户体验
通常来说对于速度的优化也蕴含在重构中
压缩 JS、CSS、image 等前端资源 (通常是由服务器来解决)
程序的性能优化 (如数据读写)
采纳 CDN 来减速资源加载
对于 JS DOM 的优化
HTTP 服务器的文件缓存
2. 列举 IE 与其余浏览器不一样的个性?
1)事件不同之处:
1-1,触发事件的元素被认为是指标(target)。而在 IE 中,指标蕴含在 event 对象的 srcElement 属性;
1-2,获取字符代码、如果按键代表一个字符(shift、ctrl、alt 除外),IE 的 keyCode 会返回字符代码(Unicode),DOM 中按键的代码和字符是拆散的,要获取字符代码,须要应用 charCode 属性;
1-3,阻止某个事件的默认行为,IE 中阻止某个事件的默认行为,必须将 returnValue 属性设置为 false,Mozilla 中,须要调用 preventDefault() 办法;
1-4,进行事件冒泡,IE 中阻止事件进一步冒泡,须要设置 cancelBubble 为 true,Mozzilla 中,须要调用 stopPropagation();
3. 什么叫优雅降级和渐进加强?
优雅降级:Web 站点在所有旧式浏览器中都能失常工作,如果用户应用的是老式浏览器,则代码会针对旧版本的 IE 进行降级解决了, 使之在新式浏览器上以某种模式降级体验却不至于齐全不能用。
如:border-shadow
渐进加强:从被所有浏览器反对的基本功能开始,逐渐地增加那些只有新版本浏览器才反对的性能, 向页面减少不影响根底浏览器的额定款式和性能的。当浏览器反对时,它们会主动地出现进去并发挥作用。
如:默认应用 flash 上传,但如果浏览器反对 HTML5 的文件上传性能,则应用 HTML5 实现更好的体验;
4. 说说严格模式的限度
严格模式次要有以下限度:
变量必须申明后再应用
函数的参数不能有同名属性,否则报错
不能应用 with 语句
不能对只读属性赋值,否则报错
不能应用前缀 0 示意八进制数,否则报错
不能删除不可删除的属性,否则报错
不能删除变量 delete prop,会报错,只能删除属性 delete global[prop]
eval 不会在它的外层作用域引入变量
eval 和 arguments 不能被从新赋值
arguments 不会主动反映函数参数的变动
不能应用 arguments.callee
不能应用 arguments.caller
禁止 this 指向全局对象
不能应用 fn.caller 和 fn.arguments 获取函数调用的堆栈
减少了保留字(比方 protected、static 和 interface)
设立 ” 严格模式 ” 的目标,次要有以下几个:
打消 Javascript 语法的一些不合理、不谨严之处,缩小一些怪异行为;
打消代码运行的一些不平安之处,保障代码运行的平安;
进步编译器效率,减少运行速度;
为将来新版本的 Javascript 做好铺垫。
注:通过测试 IE6,7,8,9 均不反对严格模式。
5. 检测浏览器版本版本有哪些形式?
依据 navigator.userAgent // UA.toLowerCase().indexOf(‘chrome’)
依据 window 对象的成员 // ‘ActiveXObject’ in window
6. 总结前端性能优化的解决方案
优化准则和方向
性能优化的准则是以更好的用户体验为规范,具体就是实现上面的指标:
多应用内存、缓存或者其余办法
缩小 CPU 和 GPU 计算,更快展示
优化的方向有两个:
缩小页面体积,晋升网络加载
优化页面渲染
缩小页面体积,晋升网络加载
动态资源的压缩合并(JS 代码压缩合并、CSS 代码压缩合并、雪碧图)
动态资源缓存(资源名称加 MD5 戳)
应用 CDN 让资源加载更快
优化页面渲染
CSS 放后面,JS 放前面
懒加载(图片懒加载、下拉加载更多)
缩小 DOM 查问,对 DOM 查问做缓存
缩小 DOM 操作,多个操作尽量合并在一起执行(DocumentFragment)
事件节流
尽早执行操作(DOMContentLoaded)
应用 SSR 后端渲染,数据间接输入到 HTML 中,缩小浏览器应用 JS 模板渲染页面 HTML 的工夫
7. 图片懒加载与预加载
图片懒加载的原理就是 临时不设置图片的 src 属性,而是将图片的 url 暗藏起来,比方先写在 data-src 外面,等某些事件触发的时候 (比方滚动到底部,点击加载图片) 再将图片实在的 url 放进 src 属性外面,从而实现图片的提早加载
图片预加载是指 在一些须要展现大量图片的网站,实现图片的提前加载。从而晋升用户体验。罕用的形式有两种,一种是暗藏在 css 的 background 的 url 属性外面,一种是通过 javascript 的 Image 对象设置实例对象的 src 属性实现图片的预加载。相干代码如下:
CSS 预加载图片形式:
#preload-01 {background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
#preload-02 {background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
#preload-03 {background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
Javascript 预加载图片的形式:
function preloadImg(url) {var img = new Image();
img.src = url;
if(img.complete) {
// 接下来能够应用图片了
//do something here
} else {img.onload = function() {
// 接下来能够应用图片了
//do something here
};
}
}
5. 形容浏览器的渲染过程,DOM 树和渲染树的区别?
浏览器的渲染过程:
解析 HTML 构建 DOM(DOM 树),并行申请 css/image/js
CSS 文件下载实现,开始构建 CSSOM(CSS 树)
CSSOM 构建完结后,和 DOM 一起生成 Render Tree(渲染树)
布局 (Layout):计算出每个节点在屏幕中的地位
显示 (Painting):通过显卡把页面画到屏幕上
DOM 树 和 渲染树 的区别:
DOM 树与 HTML 标签一一对应,包含 head 和暗藏元素
渲染树不包含 head 和暗藏元素,大段文本的每一个行都是独立节点,每一个节点都有对应的 css 属性
7. 重绘和回流(重排)的区别和关系?
重绘:当渲染树中的元素外观(如:色彩)产生扭转,不影响布局时,产生重绘
回流:当渲染树中的元素的布局(如:尺寸、地位、暗藏 / 状态状态)产生扭转时,产生重绘回流
留神:JS 获取 Layout 属性值(如:offsetLeft、scrollTop、getComputedStyle 等)也会引起回流。因为浏览器须要通过回流计算最新值
回流必将引起重绘,而重绘不肯定会引起回流
8. 如何最小化重绘 (repaint) 和回流(reflow)?
须要要对元素进行简单的操作时,能够先暗藏(display:”none”),操作实现后再显示
须要创立多个 DOM 节点时,应用 DocumentFragment 创立完后一次性的退出 document
缓存 Layout 属性值,
如:var left = elem.offsetLeft; 这样,屡次应用 left 只产生一次回流
尽量避免用 table 布局(table 元素一旦触发回流就会导致 table 里所有的其它元素回流)
防止应用 css 表达式(expression),因为每次调用都会从新计算值(包含加载页面)
尽量应用 css 属性简写,如:用 border 代替 border-width, border-style, border-color
批量批改元素款式:elem.className 和 elem.style.cssText 代替 elem.style.xxx
9.script 的地位是否会影响首屏显示工夫?
在解析 HTML 生成 DOM 过程中,js 文件的下载是并行的,不须要 DOM 解决到 script 节点。因而,script 的地位不影响首屏显示的开始工夫。
浏览器解析 HTML 是自上而下的线性过程,script 作为 HTML 的一部分同样遵循这个准则
因而,script 会提早 DomContentLoad,只显示其上局部首屏内容,从而影响首屏显示的实现工夫
存储
cookie
cookie 自身不是用来做服务器端存储的(计算机领域有很多这种“狗拿耗子”的例子,例如 CSS 中的 float),它是设计用来在服务器和客户端进行信息传递的,因而咱们的每个 HTTP 申请都带着 cookie。然而 cookie 也具备浏览器端存储的能力(例如记住用户名和明码),因而就被开发者用上了。
应用起来也非常简单,document.cookie = …. 即可。
然而 cookie 有它致命的毛病:
存储量太小,只有 4KB
所有 HTTP 申请都带着,会影响获取资源的效率
API 简略,须要封装能力用
locationStorage 和 sessionStorage
起初,HTML5 规范就带来了 sessionStorage 和 localStorage,先拿 localStorage 来说,它是专门为了浏览器端缓存而设计的。
其长处有:
存储量增大到 5MB
不会带到 HTTP 申请中
API 实用于数据存储 localStorage.setItem(key, value) localStorage.getItem(key)
sessionStorage 的区别就在于它是依据 session 过来工夫而实现,而 localStorage 会永恒无效,利用场景不同。例如,一些须要及时生效的重要信息放在 sessionStorage 中,一些不重要然而不常常设置的信息,放在 localStorage 中。
es6/7
1. 说说对 es6 的了解(说一下 es6,晓得 es6 吗)
语法糖(箭头函数,类的定义,继承),以及一些新的扩大(数组,字符串,对象,办法等),对作用域的从新定义,以及异步编程的解决方案(promise,async,await)、解构赋值的呈现
2.ES6 罕用个性
变量定义 (let 和 const, 可变与不可变,const 定义对象的非凡状况)
解构赋值
模板字符串
数组新 API(例:Array.from(),entries(),values(),keys())
箭头函数(rest 参数,扩大运算符,:: 绑定 this)
Set 和 Map 数据结构(set 实例成员值惟一存储 key 值,map 实例存储键值对(key-value))
Promise 对象(前端异步解决方案进化史,generator 函数,async 函数)
Class 语法糖(super 关键字)
3. 说说你对 Promise 的了解
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件监听——更正当和更弱小。Promise 有三种状态:pending(进行中)、fulfilled(已胜利)和 rejected(已失败)。然而无奈获取到 pending 状态,在 promise 中承受两个内置参数别离是 resolve(胜利)和 reject(失败),Promise 实例生成当前,能够用 then 办法别离指定 resolved 状态和 rejected 状态的回调函数。then 办法能够传递两个回调函数第一个是胜利,第二个是失败,失败回调也能够应用 promise 的 catch 办法回调,promise 还有一个弱小的性能那就是 all 办法能够组合多个 promise 实例,包装成一个新的 Promise 实例。
4. 介绍一下 async 和 await;
async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而 await 会期待这个 Promise 实现,并将其 resolve 的后果返回进去。
async / await 是 ES7 的重要个性 之一,也是目前社区里公认的优良异步解决方案。目前 async / await 在 IE edge 中曾经能够间接应用了,然而 chrome 和 Node.js 还没有反对。侥幸的是,babel 曾经反对 async 的 transform 了,所以咱们应用的时候引入 babel 就行。在开始之前咱们须要引入以下的 package,preset-stage- 3 里就有咱们须要的 async/await 的编译文件。
5.es6 中的 Module
ES6 中模块化语法更加简洁,应用 export 抛出,应用 import from 接管,
如果只是输入一个惟一的对象,应用 export default 即可
// 创立 util1.js 文件,内容如
export default {a: 100}
// 创立 index.js 文件,内容如
import obj from './util1.js'
如果想要输入许多个对象,就不能用 default 了,且 import 时候要加{…},代码如下
// 创立 util2.js 文件,内容如
export function fn1() {alert('fn1')
}
export function fn2() {alert('fn2')
}
// 创立 index.js 文件,内容如
import {fn1, fn2} from './util2.js’
6.ES6 class 和一般构造函数的区别
class 其实始终是 JS 的关键字(保留字),然而始终没有正式应用,直到 ES6。ES6 的 class 就是取代之前构造函数初始化对象的模式,从语法上更加合乎面向对象的写法
1)class 是一种新的语法模式,是 class Name {…} 这种模式,和函数的写法齐全不一样
2)两者比照,构造函数函数体的内容要放在 class 中的 constructor 函数中,constructor 即结构器,初始化实例时默认执行
3)class 中函数的写法是 add() {…}这种模式,并没有 function 关键字
而且应用 class 来实现继承就更加简略了
在 class 中间接 extends 关键字就能够实现继承,而不像之前的继承实现有多种不同的实现形式,在 es6 中就只有一种
留神以下两点:
应用 extends 即可实现继承,更加合乎经典面向对象语言的写法,如 Java
子类的 constructor 肯定要执行 super(),以调用父类的 constructor
7.ES6 中新增的数据类型有哪些?
Set 和 Map 都是 ES6 中新增的数据结构,是对以后 JS 数组和对象这两种重要数据结构的扩大。因为是新增的数据结构
1)Set 相似于数组,但数组能够容许元素反复,Set 不容许元素反复
2)Map 相似于对象,但一般对象的 key 必须是字符串或者数字,而 Map 的 key 能够是任何数据类型
8. 箭头函数的作用域上下文和 一般函数作用域上下文 的区别
箭头函数其实只是一个密名函数的语法糖,区别在于一般函数作用域中的 this 有特定的指向,个别指向 window,而箭头函数中的 this 只有一个指向那就是指以后函数所在的对象,其实现原理其实就是相似于之前编程的时候在函数外围定义 that 一样,用了箭头函数就不必定义 that 了间接应用 this
9.es6 如何转为 es5?
应用 Babel 转码器,Babel 的配置文件是.babelrc,寄存在我的项目的根目录下。应用 Babel 的第一步,就是配置这个文件。
算法
1. 浅拷贝 vs 深拷贝
拷贝其实就是对象复制,为了解决对象复制是产生的援用类型问题
浅拷贝:利用迭代器,循环对象将对象中的所有可枚举属性复制到另一个对象上,然而浅拷贝的有一个问题就是只是拷贝了对象的一级,其余级还如果是援用类型的值的话仍旧解决不了
深拷贝:深拷贝解决了浅拷贝的问题,利用递归的局势便当对象的每一级,实现起来较为简单,得判断值是数组还是对象,简略的说就是,在内存中存在两个数据结构完全相同又互相独立的数据,将援用型类型进行复制,而不是只复制其援用关系。
2. 常见的几种数组排序算法 JS 实现
1)疾速排序
从给定的数据中,随机抽出一项,这项的右边放所有比它小的,左边放比它大的,而后再别离这两边执行上述操作,采纳的是递归的思维,总结进去就是 实现一层,别离给两边递归,设置好进口
function fastSort(array,head,tail){
// 思考到给每个分区操作的时候都是在原有的数组中进行操作的,所以这里 head,tail 来确定分片的地位
/* 生成随机项 */
var randomnum = Math.floor(ranDom(head,tail));
var random = array[randomnum];
/* 将小于 random 的项搁置在其右边 策略就是通过一个长期的数组来贮存分好区的后果,再到原数组中替换 */
var arrayTemp = [];
var unshiftHead = 0;
for(var i = head;i <= tail;i++){if(array[i]<random){arrayTemp.unshift(array[i]);
unshiftHead++;
}else if(array[i]>random){arrayTemp.push(array[i]);
}
/* 当它等于的时候放哪,这里我想抉择放到队列的后面,也就是从 unshift 后的第一个地位搁置 */
if(array[i]===random){arrayTemp.splice(unshiftHead,0,array[i]);
}
}
/* 将对应项笼罩原来的记录 */
for(var j = head , u=0;j <= tail;j++,u++){array.splice(j,1,arrayTemp[u]);
}
/* 寻找两头项所在的 index*/
var nowIndex = array.indexOf(random);
/* 设置进口,当要放进去的片段只有 2 项的时候就能够出工了 */
if(arrayTemp.length <= 2){return;}
/* 递归,同时利用其左右两个区域 */
fastSort(array,head,nowIndex);
fastSort(array,nowIndex+1,tail);
}
2)插入排序
思维就是在曾经排好序的数组中插入到相应的地位,以从小到大排序为例,扫描曾经排好序的片段的每一项,如大于,则持续往后,直到他小于一项时,将其插入到这项的后面
function insertSort(array){
/*start 依据已排列好的项数决定 */
var start=1;
/* 按程序,每一项查看已排列好的序列 */
for(var i=start; i<array.length; start++,i++){
/* 跟已排好序的序列做比照,并插入到适合的地位 */
for(var j=0; j<start; j++){
/* 小于或者等于时(咱们是升序)插入到该项后面 */
if(array[i]<=array[j]){console.log(array[i]+' '+array[j]);
array.splice(j,0,array[i]);
/* 删除原有项 */
array.splice(i+1,1);
break;
}
}
}
}
3)冒泡排序
故名思意,就是一个个冒泡到最前端或者最初端,次要是通过两两顺次比拟,以升序为例,如果前一项比后一项大则替换程序,始终比到最初一对
function bubbleSort(array){
/* 给每个未确定的地位做循环 */
for(var unfix=array.length-1; unfix>0; unfix--){
/* 给进度做个记录,比到未确定地位 */
for(var i=0; i<unfix;i++){if(array[i]>array[i+1]){var temp = array[i];
array.splice(i,1,array[i+1]);
array.splice(i+1,1,temp);
}
}
}
}
4)抉择排序
将以后未确定块的 min 或者 max 取出来插到最后面或者前面
function selectSort(array){
/* 给每个插入后的未确定的范畴循环,初始是从 0 开始 */
for(var unfixed=0; unfixed<array.length; unfixed++){
/* 设置以后范畴的最小值和其索引 */
var min = array[unfixed];
var minIndex = unfixed;
/* 在该范畴内选出最小值 */
for(var j=unfixed+1; j<array.length; j++){if(min>array[j]){min = array[j];
minIndex = j;
}
}
/* 将最小值插入到 unfixed,并且把它所在的原有项替换成 */
array.splice(unfixed,0,min);
array.splice(minIndex+1,1);
}
}
3. 写一个数组去重的办法
/** 办法一:* 1. 构建一个新的数组寄存后果
* 2.for 循环中每次从原数组中取出一个元素,用这个元素循环与后果数组比照
* 3. 若后果数组中没有该元素,则存到后果数组中
* 缺点:不能去重数组中得援用类型的值和 NaN
*/
function unique(array){var result = [];
for(var i = 0;i < array.length; i++){if(result.indexOf(array[i]) == -1) {result.push(array[i]);
}
}
return result;
}
// [1,2,1,2,'1','2',0,'1','你好','1','你好',NaN,NaN] => [1, 2, "1", "2", 0, "你好",NaN,NaN]
// [{id: '1'}, {id: '1'}] => [{id: '1'}, {id: '1’}]
// 办法二:ES6
Array.from(new Set(array))
// [1,2,1,2,'1','2',0,'1','你好','1','你好',NaN,NaN] => [1, 2, "1", "2", 0, "你好", NaN]
4. 说一下 js 模板引擎
模板引擎原理总结起来就是:先获取 html 中对应的 id 下得 innerHTML,利用开始标签和敞开标签进行字符串切分,其实是将模板划分成两部份内容,一部分是 html 局部,一部分是逻辑局部,通过区别一些特殊符号比方 each、if 等来将字符串拼接成函数式的字符串, 将两局部各自通过解决后,再次拼接到一起,最初将拼接好的字符串采纳 new Function()的形式转化成所须要的函数。
罕用的模版引擎次要有,Template.js,handlebars.js
5. 是否理解公钥加密和私钥加密。
个别状况下是指私钥用于对数据进行签名,公钥用于对签名进行验证;
HTTP 网站在浏览器端用公钥加密敏感数据,而后在服务器端再用私钥解密。
6.js 深度复制的形式
1)应用 jq 的 $.extend(true, target, obj)
2)newobj = Object.create(sourceObj),// 然而这个是有个问题就是 newobj 的更改不会影响到 sourceobj 然而 sourceobj 的更改会影响到 newObj
3)newobj = JSON.parse(JSON.stringify(sourceObj))
7.js 设计模式
总体来说设计模式分为三大类 :
创立型模式,共五种:工厂办法模式、形象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装璜器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板办法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模
具体:详情
http://www.alloyteam.com/2012…
8. 图片懒加载与预加载?
1)图片懒加载的原理就是临时不设置图片的 src 属性,而是将图片的 url 暗藏起来,比方先写在 data-src 外面,等某些事件触发的时候 (比方滚动到底部,点击加载图片) 再将图片实在的 url 放进 src 属性外面,从而实现图片的提早加载
Javascript 预加载图片的形式:
function preloadImg(url) {var img = new Image();
img.src = url;
if(img.complete) {
// 接下来能够应用图片了
//do something here
} else {img.onload = function() {
// 接下来能够应用图片了
//do something here
};
}
}
2)图片预加载,是指在一些须要展现大量图片的网站,实现图片的提前加载。从而晋升用户体验。罕用的形式有两种,一种是暗藏在 css 的 background 的 url 属性外面,一种是通过 javascript 的 Image 对象设置实例对象的 src 属性实现图片的预加载。
CSS 预加载图片形式:
#preload-01 {background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
#preload-02 {background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
#preload-03 {background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
9. 统计字符串中次数最多字母
function findMaxDuplicateChar(str) {if(str.length == 1) {return str;}
var charObj = {};
for(var i = 0; i < str.length; i++) {if(!charObj[str.charAt(i)]) {charObj[str.charAt(i)] = 1;
} else {charObj[str.charAt(i)] += 1;
}
}
var maxChar = '',
maxValue = 1;
for(var k in charObj) {if(charObj[k] >= maxValue) {
maxChar = k;
maxValue = charObj[k];
}
}
return maxChar + ':' + maxValue;
}
19. 变态题目解析
https://juejin.im/entry/58ada…
11. 对 Node 的长处和毛病提出了本人的认识?
- (长处)因为 Node 是基于事件驱动和无阻塞的,所以非常适合解决并发申请,因而构建在 Node 上的代理服务器相比其余技术实现(如 Ruby)的服务器体现要好得多。此外,与 Node 代理服务器交互的客户端代码是由 javascript 语言编写的,因而客户端和服务器端都用同一种语言编写,这是十分美好的事件。
- (毛病)Node 是一个绝对新的开源我的项目,所以不太稳固,它总是始终在变,而且短少足够多的第三方库反对。看起来,就像是 Ruby/Rails 当年的样子。
模块化
1.commonjs?requirejs?AMD|CMD|UMD?
1)CommonJS 就是为 JS 的体现来制订标准,NodeJS 是这种标准的实现,webpack 也是以 CommonJS 的模式来书写。因为 js 没有模块的性能,所以 CommonJS 应运而生。但它不能在浏览器中运行。CommonJS 定义的模块分为:{模块援用(require)} {模块定义(exports)} {模块标识(module)}
2)RequireJS 是一个 JavaScript 模块加载器。RequireJS 有两个次要办法 (method): define() 和 require()。这两个办法基本上领有雷同的定义 (declaration) 并且它们都晓得如何加载的依赖关系,而后执行一个回调函数(callback function)。与 require() 不同的是,define()用来存储代码作为一个已命名的模块。因而 define()的回调函数须要有一个返回值作为这个模块定义。这些相似被定义的模块叫作 AMD (Asynchronous Module Definition,异步模块定义)。
3)AMD 是 RequireJS 在推广过程中对模块定义的规范化产出 AMD 异步加载模块。它的模块反对对象 函数 结构器 字符串 JSON 等各种类型的模块。实用 AMD 标准实用 define 办法定义模块。
4)CMD 是 SeaJS 在推广过程中对模块定义的规范化产出
AMD 与 CDM 的区别:
(1)对于于依赖的模块,AMD 是提前执行(如同当初也能够提早执行了),CMD 是提早执行。
(2)AMD 推崇依赖前置,CMD 推崇依赖就近。
(3)AMD 推崇复用接口,CMD 推崇单用接口。
(4)书写标准的差别。
5)umd 是 AMD 和 CommonJS 的糅合。
AMD 浏览器第一的准则倒退 异步加载模块。
CommonJS 模块以服务器第一准则倒退,抉择同步加载,它的模块无需包装(unwrapped modules)。这迫使人们又想出另一个更通用的模式 UMD (Universal Module Definition), 心愿解决跨平台的解决方案。UMD 先判断是否反对 Node.js 的模块(exports) 是否存在,存在则应用 Node.js 模块模式。
2. 模块化的了解
模块化的话其实次要就是对于 js 性能逻辑的划分,在 js 中咱们个别都吧一个 js 文件定义成一个模块,模块次要的职责就是(封装实现,裸露接口,申明依赖)
3.AMD 和 CMD 的区别
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
对于依赖的模块,AMD 是提前执行,CMD 是提早执行。不过 RequireJS 从 2.0 开始,也改成能够提早执行(依据写法不同,解决形式不同)。CMD 推崇 as lazy as possible.
CMD 推崇依赖就近,AMD 推崇依赖前置。
AMD 的 API 默认是一个当多个用,CMD 的 API 严格辨别,推崇职责繁多。比方 AMD 里,require 分全局 require 和部分 require,都叫 require。CMD 里,没有全局 require,而是依据模块零碎的齐备性,提供 seajs.use 来实现模块零碎的加载启动。CMD 里,每个 API 都简略纯正。
前端平安
1.XSS(Cross Site Scripting,跨站脚本攻打)
这是前端最常见的攻击方式,很多大型网站(如 Facebook)都被 XSS 攻打过。
举一个例子,我在一个博客网站失常发表一篇文章,输出汉字、英文和图片,齐全没有问题。然而如果我写的是歹意的 JS 脚本,例如获取到 document.cookie 而后传输到本人的服务器上,那我这篇博客的每一次浏览都会执行这个脚本,都会把访客 cookie 中的信息偷偷传递到我的服务器上来。
其实原理上就是黑客通过某种形式(公布文章、公布评论等)将一段特定的 JS 代码荫蔽地输出进去。而后他人再看这篇文章或者评论时,之前注入的这段 JS 代码就执行了。JS 代码一旦执行,那可就不受管制了,因为它跟网页原有的 JS 有同样的权限,例如能够获取 server 端数据、能够获取 cookie 等。于是,攻打就这样产生了。
XSS 的危害
XSS 的危害相当大,如果页面能够随便执行他人不平安的 JS 代码,轻则会让页面错乱、性能缺失,重则会造成用户的信息泄露。
比方早些年社交网站常常爆出 XSS 蠕虫,通过公布的文章内插入 JS,用户拜访了感化不平安 JS 注入的文章,会主动从新公布新的文章,这样的文章会通过举荐零碎进入到每个用户的文章列表背后,很快就会造成大规模的感化。
还有利用获取 cookie 的形式,将 cookie 传入入侵者的服务器上,入侵者就能够模仿 cookie 登录网站,对用户的信息进行篡改。
XSS 的预防
那么如何预防 XSS 攻打呢?—— 最基本的形式,就是对用户输出的内容进行验证和替换,须要替换的字符有:
& 替换为:&
< 替换为:<
替换为:>
”替换为:”
‘替换为:’
/ 替换为:/
替换了这些字符之后,黑客输出的攻打代码就会生效,XSS 攻打将不会轻易产生。
除此之外,还能够通过对 cookie 进行较强的管制,比方对敏感的 cookie 减少 http-only 限度,让 JS 获取不到 cookie 的内容。
2.CSRF(Cross-site request forgery,跨站申请伪造)
CSRF 是 借用了以后操作者的权限来偷偷地实现某个操作,而不是拿到用户的信息。
例如,一个领取类网站,给别人转账的接口是 http://buy.com/pay?touid=999&…,而这个接口在应用时没有任何明码或者 token 的验证,只有关上拜访就间接给别人转账。一个用户曾经登录了 http://buy.com,在抉择商品时,忽然收到一封邮件,而这封邮件注释有这么一行代码 <img src=”[http://buy.com/pay?touid=999&](http://buy.com/pay?touid=999&);money=100″/>,他拜访了邮件之后,其实就曾经实现了购买。
CSRF 的产生其实是 借助了一个 cookie 的个性。咱们晓得,登录了 http://buy.com 之后,cookie 就会有登录过的标记了,此时申请 http://buy.com/pay?touid=999&… cookie 的,因而 server 端就晓得曾经登录了。而如果在 http://buy.com 去申请其余域名的 API 例如 http://abc.com/api 时,是不会带 cookie 的,这是浏览器的同源策略的限度。然而 —— 此时在其余域名的页面中,申请 http://buy.com/pay?touid=999&…,会带着 buy.com 的 cookie,这是产生 CSRF 攻打的实践根底。
预防 CSRF 就是退出各个层级的权限验证,例如当初的购物网站,只有波及现金交易,必定要输出明码或者指纹才行。除此之外,敏感的接口应用 POST 申请而不是 GET 也是很重要的。