前端基础问题整理-JavaScript相关

请解释事件代理(event delegation)

事件代理也称为事件委托,利用了事件冒泡。例如:javascript

<ul class="item-list">
    <li class="item">item1</li>
    <li class="item">item2</li>
    <li class="item">item3</li>
</ul>

当页面li增多时单独给每一个li元素添加事件处理程序既繁琐又容易出错,利用事件冒泡,在ul去监听事件,li产生事件往上冒泡时去捕获,利用e.target来判断是否为咱们的目标元素,是的话就能够作相应操做了。html

请解释JavaScriptthis是如何工做的。

  • 做为独立函数的调用java

function func(){
    console.log(this);
}


func();
//Window

全局做用域中声明一个函数,并调用它,此时函数中的this指向全局对象。json

  • 做为对象方法调用跨域

function say(){
    console.log(this);
}

var obj = {
    name: "f2er",
    say: say
};

obj.say();
//Object {name: "f2er"}

当函数做为一个对象的方法调用时,函数中的this绑定到了这个对象。数组

  • 使用call或apply来调用函数浏览器

function func(){
    console.log(this);
}

var obj = {
    name:"f2er"
};

func.call(obj);
//Object {name: "f2er"}

func.apply(obj);
//Object {name: "f2er"}

当使用call()apply()函数进行函数调用时,传入参数对象的将被设置为函数体内this的值,这两个函数都是设置调用函数体内的this值的,且第一个参数都为this,区别是第二个参数apply()是一个参数arguments(类数组对象),而call(),传递给他的是一系列参数。安全

  • new来调用函数服务器

function F2er(name){
    this.name = name;   
    console.log(this);
}

var f2er = new F2er('f2er');
// F2er {name: "f2er"}

当使用new来调用一个函数时,会建立一个新的对象,而后绑定到Dog()调用中的this闭包

请解释原型继承(prototypal inheritance)的原理。

先上一个例子:

function Super(){
    this.superValue = "super";
}

Super.prototype.getSuperValue = function (){
    return this.superValue;
}

function Sub(){
    this.subValue = "sub";
}

var superInstance = new Super();

Sub.prototype = superInstance;

Sub.prototype.getSubValue = function (){
    return this.subValue;
}

var instance = new Sub();
console.log(instance.getSuperValue());
// super

每一个函数Sub都有一个属性prototypeprototype指向一个原型对象,原型对象中也有一个指向函数的属性constructor,经过new一个函数Sub能够产生实例instance,调用这个instance的某个属性或方法时,instance会先查找自身是否有这个方法或者属性,没有的话就会去实例的构造函数Sub的原型prototype中查找,即Sub.prototype,若是给原型对象Sub.prototype赋予另外一个类型的实例superInstance,则是在superInstance中查找的,这个superInstance中也有属性prototype指向某个原型对象,以此一级级往上最终到Object.prototype,这样就造成了原型继承。

利用此原理能够本身实现一个inherits函数:

function inherits(subType, superType){
    var _prototype = Object.create(superType.prototype);
    _prototype.constructor = subType;
    subType.prototype = _prototype;
}

IIFE(当即调用的函数表达式)是什么?有什么做用?

(function fn(){..})(),函数被包含在一个括号内,变成为一个表达式,随后跟着一个(),就当即执行这个函数,

这种模式就是当即执行函数表达式(Immediately Invoked Function Expression),简称IIFE。

也有用(function fn(){..}())后面的括号在前面的括号内这种形式表示的,这两种形式在功能上都是一致的。

IIFE的一些做用:

  • 建立做用域,内部保存一些大量临时变量的代码防止命名冲突。

  • 一些库的外层用这种形式包起来防止做用域污染。

  • 运行一些只执行一次的代码。

(function(){

    var module = require('module');

    module.setup();

    module.run();

})();
  • 用闭包保存状态

如下点击页面标签的时候,实际并非弹出每一个具体的i的,而是elems.length,由于每一个a监听器中引用的i都是同一个做用域的。

var elems = document.getElementsByTagName('a');

for (var i = 0; i < elems.length; i++) {
    elems[i].addEventListener('click', function (e) {
        e.preventDefault();
        alert('I am link #' + i);
    }, 'false');
}

如下点击页面标签的时候,每个i传入一个IIFEIIFE造成单独一个做用域保存了当时的i值,因此点击a标签,能够弹出不一样的i值。

var elems = document.getElementsByTagName('a');

for (var i = 0; i < elems.length; i++) {
    (function (lockedInIndex) {
        elems[i].addEventListener('click', function (e) {
            e.preventDefault();
            alert('I am link #' + lockedInIndex);
        }, 'false');
    })(i);
}

什么是闭包(closure),有什么做用?

当某个函数调用时会建立一个执行环境以及做用域链,而后根据arguments和其它命名参数初始化造成活动对象。在外部函数调用结束后,其执行环境与做用域链被销毁,可是其活动对象保存在了闭包之中,最后在闭包函数调用结束后才销毁。简单的说,闭包就是可以读取其余函数内部变量的函数。在js中,闭包是指有权访问另外一个函数做用域中的变量的函数。

闭包的做用

  • 匿名自执行函数

有的场景下函数只须要执行一次,例如init()之类的函数,其内部变量无需维护,咱们可使用闭包。 咱们建立了一个匿名的函数,并当即执行它,因为外部没法引用它内部的变量,所以在函数执行完后会马上释放资源,并且不污染全局对象

  • 封装

模拟面向对象的代码风格进行封装,使私有属性存在成为可能。

缺点

  • 常驻内存,会增大内存使用量,易形成内存泄露

请指出JavaScript宿主对象和原生对象的区别?

  • 宿主对象是指DOMBOM

  • 原生对象是Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、Math等对象。

请指出如下代码的区别:function Person(){}、var person = Person()、var person = new Person()?

  • function Person(){}

声明一个函数Person()

  • var person = Person()

将函数Person()的结果返回给变量person,若是没有返回值则personundefined

  • var person = new Person()

new一个Person的实例对象。

.call.apply的区别是什么?

.call.apply的共同点是都是用来改变函数体内this对象的值。

区别是第二个参数不同。apply()的第二个参数是一个类数组对象arguments,参数都是以数组的形式传入,而call(),传递给他的是一系列参数。例如

Math.max.call(null, 1, 2, 3, 4);
//4

Math.max.apply(null, [1, 2, 3, 4]);
//4

请解释Function.prototype.bind

Function.prototype.bind方法会建立一个新函数,当这个新函数被调用时,它的this值是传递给bind()的第一个参数, 它的参数是bind()的其余参数和其本来的参数.

Function.prototype.bind的实现相似于:

Function.prototype.bind = function (scope) {
    var fn = this;
    return function () {
        return fn.apply(scope, arguments);
    };
}

Function.prototype.bind的做用

  • 建立绑定函数

  • 一些函数的参数经常也是函数,给当作参数的函数绑定this值确保参数函数执行时有正确的this指向。

Ajax的工做原理

Ajax是无需刷新页面就能从服务器取得数据的一种方法。

原理

Ajax经过XmlHttpRequest对象来向服务器发异步请求,从服务器得到数据,而后用javascript来操做DOM更新页面。

过程

  1. 建立XMLHttpRequest对象。

  2. 设置响应HTTP请求的回调函数。

  3. 建立一个HTTP请求,指定相应的请求方法、url等。

  4. 发送HTTP请求。

  5. 获取服务器端返回的数据。

  6. 使用JavaScript操做DOM更新页面。

缺点

  • 对搜索引擎不友好

  • 要实现Ajax下的先后退功能成本较大

  • 跨域问题限制

JSONP的工做原理

JSONP(JSON with Padding)是一种非官方跨域数据交互协议,它容许在服务器端集成<script>标签返回至客户端,经过javascript回调的形式实现跨域访问。

由于同源策略的缘由,咱们不能使用XMLHttpRequest与外部服务器进行通讯,可是<script>能够访问外部资源,因此经过JSON<script>相结合的办法,能够绕过同源策略从外部服务器直接取得可执行的JavaScript函数。

原理

客户端定义一个函数,好比jsonpCallback,而后建立<script>srcurl + ?jsonp=jsonpCallback这样的形式,以后服务器会生成一个和传递过来jsonpCallback同样名字的参数,并把须要传递的数据当作参数传入,好比jsonpCallback(json),而后返回给客户端,此时客户端就执行了这个服务器端返回的jsonpCallback(json)回调。

通俗的说,就是客户端定义一个函数而后请求,服务器端返回的javascript内容就是调用这个函数,须要的数据都当作参数传入这个函数了。

  • 优势 - 兼容性好,简单易用,支持浏览器与服务器双向通讯

  • 缺点 - 只支持GET请求;存在脚本注入以及跨站请求伪造等安全问题

补充一点,JSONP不使用XMLHttpRequest对象加载资源,不属于真正意义上的AJAX

变量声明提高(hoisting)

变量的声明前置就是把变量的声明提高到当前做用域的最前面。

函数的声明前置就是把整个函数提高到当前做用域的最前面(位于前置的变量声明后面)。

//变量的声明前置

console.log(num);//undefined

var num = 1;



等价于



//变量的声明前置

var num;

console.log(num);//undefined

num = 1;
//函数的声明前置

var num = 1;

console.log(doubleNum(num));//2

function doubleNum(num){

    return num*2;

}



等价于



//函数的声明前置

var num;

function doubleNum(num){

    return num*2;

}

num = 1;

console.log(doubleNum(num));//2

事件冒泡机制(event bubbling)

事件冒泡(event bubbling),事件最开始时由触发的那个元素身上发生,而后沿着DOM树向上传播,直到document对象。若是想阻止事件起泡,可使用e.stopPropagation()

JavaScript的同源策略

同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式。同源指的是协议、域名、端口相同,同源策略是一种安全协议。

目的

同源策略保证了用户的信息安全,浏览器打开多个站点时,互相之间不能利用JavaScript获取对方站点的敏感信息。

一些跨域技术

  • JSONP

  • CORS

  • 修改document.domain来进行跨域

  • 使用window.name来进行跨域

  • 使用window.postMessage来进行跨域

什么是"use strict"?使用它的好处和坏处分别是什么?

在全部语句以前放一个特定语句"use strict",就会为整个script标签开启严格模式。

优势

  • 消除Javascript语法的一些不严谨之处,减小一些怪异行为;

  • 消除代码运行的一些不安全之处,保证代码运行的安全;

  • 提升编译器效率,增长运行速度;

  • 为将来新版本的Javascript作好铺垫。

缺点

  • 严格模式改变了语义。依赖这些改变可能会致使没有实现严格模式的浏览器中出现问题或者错误。

相关文章
相关标签/搜索