请解释事件代理 (event delegation)。
将单个事件绑定在父对象上,利用冒泡机制, 监听来自子元素的事件。
优点:解决子元素增加删除时候的事件处理,防止内存泄漏
事件捕获:当某个元素触发某个事件(如 onclick),顶层对象 document 就会发出一个事件流,随着 DOM 树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。
事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
事件起泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用 e.stopPropagation()(Firefox)或者 e.cancelBubble=true(IE)来组织事件的冒泡传播。
请解释 JavaScript 中 this 是如何工作的。
stackoverflow
在全局环境时
// this 表示 window
function f(){
return this // 也是 window
}
放在 object 方法里面时
this 绑定到包含他的对象
var obj = {
name: “obj”,
f: function () {
return this + “:” + this.name;
}
};
document.write(obj.f());
var obj = {
name: “obj1″,
nestedobj: {
name:”nestedobj”,
f: function () {
return this + “:” + this.name;
}
}
}
document.write(obj.nestedobj.f()); //[object Object]:nestedobj
即使你隐式的添加方法到对象,this 仍然指向立即父对象
var obj1 = {
name: “obj1”,
}
function returnName() {
return this + “:” + this.name;
}
obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1
当调用一个无上下问的函数
当函数调用没有包含上下文,this 将绑定到 global 对象
var context = “global”;
var obj = {
context: “object”,
method: function () {
function f() {
var context = “function”;
return this + “:” +this.context;
};
return f(); //invoked without context
}
};
document.write(obj.method()); //[object Window]:global
当使用在构造函数时
即使用 new 关键字时,this 指向刚创建的对象
var myname = “global context”;
function SimpleFun()
{
this.myname = “simple function”;
}
var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
// object being constructed thus adding any member
// created inside SimipleFun() using this.membername to the
// object being constructed
//2. And by default `new` makes function to return newly
// constructed object if no explicit return value is specified
document.write(obj1.myname); //simple function
当内部对象定义在原型链时
当一个方法定义在对象原型链,this 指向调用该方法的对象
var ProtoObj = {
fun: function () {
return this.a;
}
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun()
//to be the method on its prototype chain
var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999
//Notice that fun() is defined on obj3’s prototype but
//`this.a` inside fun() retrieves obj3.a
在 call(), apply() and bind() 函数内部
fun.apply(obj1 [, argsArray])
fun.call(obj1 [, arg1 [, arg2 [,arg3 [, …]]]])
设置 this 函数并执行
fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, …]]]])
设置 this
this 在事件处理上
如果函数在 eventHandler 和 onclick 直接被调用 this 指向元素 (currentTarget) 否则执行 window
<script>
function clickedMe() {
alert(this + ” : ” + this.tagName + ” : ” + this.id);
}
document.getElementById(“button1”).addEventListener(“click”, clickedMe, false);
document.getElementById(“button2”).onclick = clickedMe;
document.getElementById(“button5”).attachEvent(‘onclick’, clickedMe);
</script>
<h3>Using `this` “directly” inside event handler or event property</h3>
<button id=”button1″>click() “assigned” using addEventListner() </button><br />
<button id=”button2″>click() “assigned” using click() </button><br />
<button id=”button3″ onclick=”alert(this+ ‘ : ‘ + this.tagName + ‘ : ‘ + this.id);”>used `this` directly in click event property</button>
<h3>Using `this` “indirectly” inside event handler or event property</h3>
<button onclick=”alert((function(){return this + ‘ : ‘ + this.tagName + ‘ : ‘ + this.id;})());”>`this` used indirectly, inside function <br /> defined & called inside event property</button><br />
<button id=”button4″ onclick=”clickedMe()”>`this` used indirectly, inside function <br /> called inside event property</button> <br />
IE only: <button id=”button5″>click() “attached” using attachEvent() </button>
请解释原型继承 (prototypal inheritance) 的原理。
当定义一个函数对象的时候,会包含一个预定义的属性,叫 prototype,这就属性称之为原型对象。
function F(){};
console.log(F.prototype)
//F.prototype 包含
//contructor 构造函数
JavaScript 在创建对象的时候,都会有一个 [[proto]] 的内置属性,用于指向创建它的函数对象的 prototype。原型对象也有 [[proto]] 属性。因此在不断的指向中,形成了原型链。
// 函数对象
function F(){};
F.prototype = {
hello : function(){}
};
var f = new F();
console.log(f.__proto__)
当使用 new 去调用构造函数时,相当于执行了
var o = {};
o.__proto__ = F.prototype;
F.call(o);
原型对象 prototype 上都有个预定义的 constructor 属性,用来引用它的函数对象。这是一种循环引用。
function F(){};
F.prototype.constructor === F;
(new Foo).__proto__ === Foo.prototype
(new Foo).prototype === undefined
__proto__真正的原型链 prototype 只存在与构造函数中
你怎么看 AMD vs. CommonJS?
请解释为什么接下来这段代码不是 IIFE (立即调用的函数表达式):function foo(){}();.
没有加括号
要做哪些改动使它变成 IIFE?
描述以下变量的区别:null,undefined 或 undeclared?
该如何检测它们?
null===null
undefined === undefined
什么是闭包 (closure),如何使用它,为什么要使用它?
函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外
请举出一个匿名函数的典型用例?
回调
你是如何组织自己的代码?是使用模块模式,还是使用经典继承的方法?
请指出 JavaScript 宿主对象 (host objects) 和原生对象 (native objects) 的区别?
请指出以下代码的区别:function Person(){}、var person = Person()、var person = new Person()?
.call 和 .apply 的区别是什么?
apply 第二个参数是数组 call 第二个以后的可变参数
请解释 Function.prototype.bind?
在什么时候你会使用 document.write()?
写 script
请指出浏览器特性检测,特性推断和浏览器 UA 字符串嗅探的区别?
请尽可能详尽的解释 Ajax 的工作原理。
XMLHttpRequest
使用 Ajax 都有哪些优劣?
请解释 JSONP 的工作原理,以及它为什么不是真正的 Ajax。
通过在网页中加入 script 标签,是浏览器通过 get 方式加载一段 js 代码
你使用过 JavaScript 模板系统吗?
如有使用过,请谈谈你都使用过哪些库?
请解释变量声明提升 (hoisting)。
通过 var 声明的变量在代码执行之前被 js 引擎提升到了当前作用域的顶部
请描述事件冒泡机制 (event bubbling)。
一个事件被触发,会发生先捕获后冒泡的行为。冒泡机制指一个事件从发生元素开始先父元素传递,直到达到根元素
“attribute” 和 “property” 的区别是什么?
js dom 对象拥有的 property,property 有很多类型 attribute 是指 html 拥有的特性,类型是字符串
为什么扩展 JavaScript 内置对象不是好的做法?
请指出 document load 和 document DOMContentLoaded 两个事件的区别。
DomContentLoaded 事件发生在 domcument 对象被初始化完成,css,图片和 frame 还没被加载的时候
load 事件表示资源被全部加载
== 和 === 有什么不同?
== 会发生类型转换 === 不会发生类型转换
请解释 JavaScript 的同源策略 (same-origin policy)。
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互
http://store.company.com/dir2… 成功 http://store.company.com/dir/… 成功 https://store.company.com/sec… 失败 不同协议 (https 和 http)http://store.company.com:81/dir/etc.html 失败 不同端口 (81 和 80)http://news.company.com/dir/o… 失败 不同域名 (news 和 store
如何实现下列代码:
[1,2,3,4,5].duplicator(); // [1,2,3,4,5,1,2,3,4,5]
Arrry.prototype.duplicator = function(){
return this.concat(this)
}
什么是三元表达式 (Ternary expression)?“三元 (Ternary)”表示什么意思?
什么是 “use strict”; ? 使用它的好处和坏处分别是什么?
“use strict” 告诉 js 运行时以严格模式执行 javascript 语句使 js 以更安全的方式执行,对某些行为直接报错
请实现一个遍历至 100 的 for loop 循环,在能被 3 整除时输出 “fizz”,在能被 5 整除时输出 “buzz”,在能同时被 3 和 5 整除时输出 “fizzbuzz”。
for(let i=1;i<=100;i++){
let word = “”
if(i % 3 ==0){
word += “fizz”
}
if(i % 5 ==0){
word += “buzz”
}
if(word){
console.log(word)
}
}
为何通常会认为保留网站现有的全局作用域 (global scope) 不去改变它,是较好的选择?
为何你会使用 load 之类的事件 (event)?此事件有缺点吗?你是否知道其他替代品,以及为何使用它们?
请解释什么是单页应用 (single page app), 以及如何使其对搜索引擎友好 (SEO-friendly)。
单页应用是指所有的资源交互都放在一个页面,而不是交换的时候跳转到另一个页面。使用 ssr 服务端渲染。
你使用过 Promises 及其 polyfills 吗? 请写出 Promise 的基本用法(ES6)。
new Promise(resolve,reject)
Promise.resolve
Promise.reject
使用 Promises 而非回调 (callbacks) 优缺点是什么?
将回调转换成链式调用
使用一种可以编译成 JavaScript 的语言来写 JavaScript 代码有哪些优缺点?
你使用哪些工具和技术来调试 JavaScript 代码?
console.logdebuger
你会使用怎样的语言结构来遍历对象属性 (object properties) 和数组内容?
array array.foreachobject for var i in xx i 是字符串
请解释可变 (mutable) 和不变 (immutable) 对象的区别。
mutableimuutable 表示对象创建后就不再变化
请举出 JavaScript 中一个不变性对象 (immutable object) 的例子?
不变性 (immutability) 有哪些优缺点?
可以比较对象,线程安全缺点就是费内存
如何用你自己的代码来实现不变性 (immutability)?
请解释同步 (synchronous) 和异步 (asynchronous) 函数的区别。
同步是指顺序执行,会有阻塞异步是指函数立即执行并返回
什么是事件循环 (event loop)?
主线程运行的时候,产生堆(heap)和栈(stack),栈中的代码调用各种外部 API,它们在 ” 任务队列 ” 中加入各种事件(click,load,done)。只要栈中的代码执行完毕,主线程就会去读取 ” 任务队列 ”,依次执行那些事件所对应的回调函数。
请问调用栈 (call stack) 和任务队列 (task queue) 的区别是什么?
javascript 中的所有任务分为两类,一类是同步任务,另一种是一部任务。所有的同步任务都在主线程上执行,当同步任务执行完在执行异步任务。
call stack 指主线线程执行任务的地方,当调用栈为空的时候,会去轮询 task queue,然后将队列里的任务加入栈中执行 tast queue 按照包含一系列任务的队列
解释 function foo() {} 与 var foo = function() {} 用法的区别
第一个表示生成一个命名的函数第二个表示生成一个匿名函数,并赋值给 foo
What are the differences between variables created using let, var or const?
let var const 都表示申明一个变量
var 的作用于是函数体的全部,会发生作用于提升 let,const 是块级作用域 let 表示可以被多次赋值 const 表示只能被一次赋值
{} + {}
js 的加法只有两种
字符串和字符串的相加
数字和数字的相加
加法运算会触发三种转换
原始值
数字
字符串
> [] + []
”
//[].toString()为空字符串, 空字符串相加
> [] + {}
‘[object Object]’
> {} + {}
‘NaN’
// 火狐下为 NaN 因为第一个对象当作空代码块,实际执行为 +{}