前端面试笔记 - js相关

更新于 2019-01-20  约 19 分钟

请解释事件代理 (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.log
debuger

你会使用怎样的语言结构来遍历对象属性 (object properties) 和数组内容?

array array.foreach
object for var i in xx i是字符串

请解释可变 (mutable) 和不变 (immutable) 对象的区别。

mutable
imuutable表示对象创建后就不再变化

请举出 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的加法只有两种

  1. 字符串和字符串的相加
  2. 数字和数字的相加

加法运算会触发三种转换

  1. 原始值
  2. 数字
  3. 字符串
> [] + []
''
//[].toString()为空字符串,空字符串相加

> [] + {}
'[object Object]'

> {} + {}
'NaN' 
// 火狐下为NaN 因为第一个对象当作空代码块,实际执行为 +{}
阅读 345更新于 2019-01-20

推荐阅读
目录