03月22, 2018

前端面试常见问题

1、eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。

Javascript 的 eval 函数可以在当前作用域执行一段包含 Javascript 代码的字符串。如下:

var foo = 1;
function test() {
    var foo = 2;
    eval('foo = 3');
    return foo;
}
test(); // 3
foo; // 1

然而,eval 函数只有在当前作用域中直接被调用并且被调用的函数名为 eval 才会被执行。

var foo = 1;
function test() {
    var foo = 2;
    var bar = eval;
    bar('foo = 3');
    return foo;
}
test(); // 2
foo; // 3

eval 函数的使用应该被避免,99.9% 使用 eval 函数所实现的功能都可以通过不使用 eval 函数来实现。

eval 函数毫无疑问将会造成安全问题,因为它会执行任何传给它的字符串,所以永远不要对未知或未信任源传来的字符串使用 eval 函数。

2、new Function ([arg1[, arg2[, ...argN]],] functionBody)也需要慎用。

var sum = new Function('a', 'b', 'return a+b');

console.log(sum(2, 6));
// expected output: 8
var sum = new Function('a', 'b', 'alert(123)');

console.log(sum(2, 6));
// > undefined

new Function ([arg1[, arg2[, ...argN]],] functionBody)

functionBody 一个含有包括函数定义的JavaScript语句的字符串。

3、简述WEB的几种常见的攻击以及防御方法,例如XSS、CSRF 和 SQL 注入

XSS:跨站脚本攻击

跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。在WEB A上通过javascript获取document.cookie,并传递给自己的WEB B。

CSRF:跨站请求伪造

CSRF定义: 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

SQL 注入

SQL攻击(英语:SQL injection),简称注入攻击,是发生于应用程序之数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏或是入侵。

4、cookie和session的区别

Cookie是保存到浏览器端的,Session是保存到服务器端的,但通常保存在服务器端的session需要根据保存在Cookie中的session_id来进行区分,具体参见Session和Cookie的区别

5、什么是箭头函数?

“箭头函数”的this,总是指向定义时所在的对象,而不是运行时所在的对象。

在箭头函数出现之前,每个新定义的函数都有它自己的 this值(在构造函数的情况下是一个新对象,在严格模式的函数调用中为 undefined,如果该函数被称为“对象方法”则为基础对象等)。This被证明是令人厌烦的面向对象风格的编程。

function Person() {
  // Person() 构造函数定义 `this`作为它自己的实例.
  this.age = 0;

  setInterval(function growUp() {
    // 在非严格模式, growUp()函数定义 `this`作为全局对象, 
    // 与在 Person()构造函数中定义的 `this`并不相同.
    this.age++;
    console.log(this.age);
  }, 1000);
}
//    > NaN

var p = new Person();

在ECMAScript 3/5中,通过将this值分配给封闭的变量,可以解决this问题。

function Person() {
  var that = this;
  that.age = 0;

  setInterval(function growUp() {
    //  回调引用的是`that`变量, 其值是预期的对象. 
    that.age++;
    console.log(that.age);
  }, 1000);
}
// > 1 > 2 > 3 > ...
var p = new Person();

箭头函数不会创建自己的this;它使用封闭执行上下文的this值。因此,在下面的代码中,传递给setInterval的函数内的this与封闭函数中的this值相同:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| 正确地指向person 对象
    console.log(this.age);
  }, 1000);   
}
// > 1 > 2 > 3 > ...
var p = new Person();

6、什么是闭包?

当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。

简单的来说,所谓的闭包就是一个具有封闭的对外不公开的,包裹结构或空间。

为什么函数可以构成闭包?

闭包就是一个具有封闭与包裹功能的结构,是为了实现具有私有访问空间的函数的。函数可以构成闭包。函数内部定义的数据函数外部无法访问,即函数具有封闭性;函数可以封装代码即具有包裹性,所以函数可以构成闭包。

闭包的作用,就是保存自己私有的变量,通过提供的接口(方法)给外部使用,但外部不能直接访问该变量。

当我们需要在模块中定义一些变量,并希望这些变量一直保存在内存中但又不会“污染”全局的变量时,就可以用闭包来定义这个模块。

闭包的缺点:闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

函数套函数就是闭包吗?:不是!,当一个内部函数被其外部函数之外的变量引用时,才会形成了一个闭包。

function createPerson() {
    var __name__ = "";
    return {
        getName: function () {
            return __name__;
        },
        setName: function( value ) {
            // 如果不姓张就报错
            if ( value.charAt(0) === '张' ) {
                __name__ = value;
            } else {
                throw new Error( '姓氏不对,不能取名' );
            }
        }
    }
}
var p = createPerson();
p.setName( '张三丰' );
console.log( p.getName() );
p.setName( '张君宝' );
console.log( p.getName() );
//> "张三丰"
//> "张君宝"

7、HTTPS的握手过程

浏览器将自己支持的一套加密规则发送给服务器。

服务器从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。

浏览器获得网站证书之后浏览器要做以下工作:

验证证书的合法

如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。

使用约定好的HASH算法计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给服务器

网站接收浏览器发来的数据之后要做以下的操作:

使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。

使用密码加密一段握手消息,发送给浏览器。

浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。

8、ECMAScript、JavaScript和JScript的区别?

ECMAscript是javascript和Jscript的标准,javascript是面向所有浏览器的,Jscript只是面向微软的IE,两者差不多,但是有自己的扩展,但是都是按照ECMAscript的标准来制定的。

具体可以参考:https://www.oschina.net/translate/whats-the-difference-between-javascript-and-ecmascript

9、什么是JavaScript 严格模式(use strict)?

x = 3.14;       // 不报错 
myFunction();

function myFunction() {
   "use strict";
    y = 3.14;   // 报错 (y 未定义)
}

为什么使用严格模式:

消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;

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

提高编译器效率,增加运行速度;

为未来新版本的Javascript做好铺垫。

"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。

另一方面,同样的代码,在"严格模式"中,可能会有不一样的运行结果;一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行。掌握这些内容,有助于更细致深入地理解Javascript,让你变成一个更好的程序员。

具体限制参考: http://www.runoob.com/js/js-strict.html

10、ng-if 跟 ng-show/hide 的区别有哪些?

第一点区别是,ng-if 在后面表达式为 true 的时候才创建这个 dom 节点,ng-show 是初始时就创建了,用 display:block 和 display:none 来控制显示和不显示。

第二点区别是,ng-if 会(隐式地)产生新作用域,ng-switch 、 ng-include 等会动态创建一块界面的也是如此。

这样会导致,在 ng-if 中用基本变量绑定 ng-model,并在外层 div 中把此 model 绑定给另一个显示区域,内层改变时,外层不会同步改变,因为此时已经是两个变量了。


<p>{{name}}</p>
<div ng-if="true">
    <input type="text" ng-model="name">
</div>

ng-show 不存在此问题,因为它不自带一级作用域。

避免这类问题出现的办法是,始终将页面中的元素绑定到对象的属性(data.x)而不是直接绑定到基本变量(x)上。

VUE相关

11、什么是事件冒泡?怎么阻止事件冒泡?

阻止事件冒泡:

a) 原生js方式,依赖于事件对象

b) vue方式,不依赖于事件对象
    @click.stop

12、什么是VUEX?

13、VUE怎么发送AJAX请求?

14、Vue的生命周期

15、什么是组件?组件间怎么数据传递 (通信)?

组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。组件是自定义元素(对象)

父子组件

在一个组件内部定义另一个组件,称为父子组件

子组件只能在父组件内部使用

默认情况下,子组件无法访问父组件中的数据,每个组件实例的作用域是独立的

子组件访问父组件的数据

a)在调用子组件时,绑定想要获取的父组件中的数据

b)在子组件内部,使用props选项声明获取的数据,即接收来自父组件的数据

总结:父组件通过props向下传递数据给子组件

注:组件中的数据共有三种形式:data、props、computed

父组件访问子组件的数据

a)在子组件中使用vm.$emit(事件名,数据)触发一个自定义事件,事件名自定义

b)父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法,用来获取数据

总结:子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件

单向数据流

props是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来 而且不允许子组件直接修改父组件中的数据,报错

解决方式: 方式1:如果子组件想把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据

方式2:如果子组件想修改数据并且同步更新到父组件,两个方法:

    a.使用.sync(1.0版本中支持,2.0版本中不支持,2.3版本又开始支持)
        需要显式地触发一个更新事件

    b.可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间),推荐

非父子组件间的通信

非父子组件间的通信,可以通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件


var Event=new Vue();
Event.$emit(事件名,数据);
Event.$on(事件名,data => {});

16、什么是vue-router路由?

使用Vue.js开发SPA(Single Page Application)单页面应用

根据不同url地址,显示不同的内容,但显示在同一个页面中,称为单页面应用

17、display:none与visibility:hidden的区别是什么?

display : 隐藏对应的元素但不挤占该元素原来的空间。

visibility: 隐藏对应的元素并且挤占该元素原来的空间。

  即是,使用CSS display:none属性后,HTML元素(对象)的宽度、高度等各种属性值都将“丢失”;而使用visibility:hidden属性后,HTML元素(对象)仅仅是在视觉上看不见(完全透明),而它所占据的空间位置仍然存在。

18、CORS(Cross-origin resource sharing)是什么?

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

参考: http://www.ruanyifeng.com/blog/2016/04/cors.html

19、CSS 如何计算优先级?

就近原则,同权重情况下以样式定义最近者为准;

载入样式以最后载入的定位为准;

优先级:

    !important > id > class > tag
    important 比 内联优先级高

20、介绍一下 Sass 和 Less 是什么?它们有何区别?

Sass (Syntactically Awesome Stylesheets)是一种动态样式语言,语法跟css一样(但多了些功能),比css好写,而且更容易阅读。Sass语法类似与Haml,属于缩排语法(makeup),用意就是为了快速写Html和Css。

Less一种动态样式语言. 将CSS赋予了动态语言的特性,如变量,继承,运算, 函数. LESS 既可以在客户端上运行 (支持IE 6+, Webkit, Firefox),也可一在服务端运行 (借助 Node.js)。

区别:

(1))Sass是基于Ruby的,是在服务端处理的,而Less是需要引入less.js来处理Less代码输出Css到浏览器,也可以在开发环节使用Less,然后编译成Css文件,直接放到项目中,也有Less.app、SimpleLess、CodeKit.app这样的工具,也有在线编译地址。

(2)变量符不一样,less是@,而Scss是$,而且变量的作用域也不一样。

(3)输出设置,Less没有输出设置,Sass提供4中输出选项:nested, compact, compressed 和 expanded。

(4)Sass支持条件语句,可以使用if{}else{},for{}循环等等。而Less不支持。

21、Doctype作用?标准模式与兼容模式各有什么区别?

(1)<!DOCTYPE>声明位于HTML文档中的第一行,处于标签之前,用于告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。

(2)标准模式的排版和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。

参考:https://www.jianshu.com/p/65fa501e4683

22、ECMAScript with 语句

有标签的语句 with 语句用于设置代码在特定对象中的作用域。

它的语法:

with (expression) statement

例如:

var sMessage = "hello";
with(sMessage) {
  alert(toUpperCase());    //输出 "HELLO"
}

本文链接:https://www.daguanren.cc/post/interview_question_front_end.html

-- EOF --

大官人捐赠
大官人微信 大官人支付宝

Comments