前端面试大全(JavaScript篇——面试利器值得拥有!)

25 篇文章 8 订阅
7 篇文章 3 订阅

目录

面试系列

后续更新分类将同步更新系列目录:

内容介绍

  前端面试大全(JavaScript篇——面试利器值得拥有!)。

1、介绍js的基本数据类型。

Undefined、Null、Boolean、Number、String

2、介绍js有哪些内置对象?

Object 是JavaScript 中所有对象的父对象

  • 数据封装类对象:Object、Array、Boolean、Number 和String
  • 其他对象:Function、Arguments、Math、Date、RegExp、Error
3、说几条写JavaScript的基本规范?,
  • 不要在同一行声明多个变量。
  • 请使用===/!==来比较true/false或者数值
  • 使用对象字面量替代new Array这种形式
  • 不要使用全局函数。
  • Switch语句必须带有default分支
  • 函数不应该有时候有返回值,有时候没有返回值。
  • For循环必须使用大括号
  • If语句必须使用大括号
  • for-in循环中的变量应该使用var关键字明确限定作用域,从而避免作用域污染。
4、JavaScript原型,原型链? 有什么特点?
  • 每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
  • 如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
  • 于是就这样一直找下去,也就是我们平时所说的原型链的概念。
一、关系

instance.constructor.prototype = instance.__proto__

二、特点
  • JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
    当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性,如果没有的话,
  • 就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到Object 内建对象。
function Func(){}
 Func.prototype.name = "Sean";
Func.prototype.getInfo = function() {
return this.name;
 }
var person = new Func();//现在可以参考var person = Object.create(oldObject);
console.log(person.getInfo());//它拥有了Func的属性和方法
//"Sean"
console.log(Func.prototype);
 // Func { name="Sean", getInfo=function()}
5、JavaScript有几种类型的值?,你能画一下他们的内存图吗?
  • :原始数据类型(Undefined,Null,Boolean,Number、String)

  • :引用数据类型(对象、数组和函数)

  • 两种类型的区别是:存储位置不同;

  • 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;

  • 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体

6、Javascript如何实现继承?
  1. 构造继承
  2. 原型继承
  3. 实例继承
  4. 拷贝继承

原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式。

 function Parent(){
this.name = 'wang';
}
function Child(){
this.age = 28;
}
Child.prototype = new Parent();//继承了Parent,通过原型
var demo = new Child();
alert(demo.age);
alert(demo.name);//得到被继承的属性
7、javascript创建对象的几种方式?

javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON;但写法有很多种,也能混合使用。

一、对象字面量的方式
person={firstname:"Bai",lastname:"Suzhen",age:18,eyecolor:"black"};
二、用function来模拟无参的构造函数
function Person(){}
var person=new Person();
//定义一个function,如果使用new"实例化",该function可以看作是一个Class
person.name=“Bai";
person.age="18";
person.work=function(){
alert(person.name+" hello...");
}
person.work();
三、用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+",是个programer");
 }
 }
var maidou =new Pet("大炮",18,"coding");
//实例化、创建对象
maidou.eat();//调用eat方法
四、用工厂方式来创建(内置对象)
 var wcDog =new Object();
 wcDog.name="咪咪";
wcDog.age=3;
wcDog.work=function(){
alert("我是"+wcDog.name+",喵喵......");
 }
wcDog.work();
五、用原型方式来创建
function Dog(){ }
Dog.prototype.name="咪咪";
Dog.prototype.eat=function(){alert(this.name+"是个吃货");}
var wangcai =new Dog();
wangcai.eat();
六、用混合方式来创建
function Car(name,price){
this.name=name;
this.price=price;
}
Car.prototype.sell=function(){
alert("我是"+this.name+",我现在卖"+this.price+"元");
 }
 var camry =new Car("老冰棍",2);
camry.sell();
8、Javascript作用链域?

作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的。

9、谈谈This对象的理解。
  • this总是指向函数的直接调用者(而非间接调用者);
  • 如果有new关键字,this指向new出来的那个对象;
  • 在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window;
  • this就是指的是当前对象
10、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)作为对象原型链的终点。
11、写一个通用的事件侦听器函数。

event(事件)工具集,来源:github.com/markyun

    markyun.Event = {
        // 页面加载完成后
        readyEvent : function(fn) {
            if (fn==null) {
                fn=document;
            }
            var oldonload = window.onload;
            if (typeof window.onload != 'function') {
                window.onload = fn;
            } else {
                window.onload = function() {
                    oldonload();
                    fn();
                };
            }
        },
        // 视能力分别使用dom0||dom2||IE方式来绑定事件
        // 参数:操作的元素,事件名称,事件处理程序
        addEvent : function(element, type, handler) {
            if (element.addEventListener) {
                //事件类型、需要执行的函数、是否捕捉
                element.addEventListener(type, handler, false);
            } else if (element.attachEvent) {
                element.attachEvent('on' + type, function() {
                    handler.call(element);
                });
            } else {
                element['on' + type] = handler;
            }
        },
        // 移除事件
        removeEvent : function(element, type, handler) {
            if (element.removeEventListener) {
                element.removeEventListener(type, handler, false);
            } else if (element.datachEvent) {
                element.detachEvent('on' + type, handler);
            } else {
                element['on' + type] = null;
            }
        },
        // 阻止事件(主要是事件冒泡,因为IE不支持事件捕获)
        stopPropagation : function(ev) {
            if (ev.stopPropagation) {
                ev.stopPropagation();
            } else {
                ev.cancelBubble = true;
            }
        },
        // 取消事件的默认行为
        preventDefault : function(event) {
            if (event.preventDefault) {
                event.preventDefault();
            } else {
                event.returnValue = false;
            }
        },
        // 获取事件目标
        getTarget : function(event) {
            return event.target || event.srcElement;
        },
        // 获取event对象的引用,取到事件的所有信息,确保随时能使用event;
        getEvent : function(e) {
            var ev = e || window.event;
            if (!ev) {
                var c = this.getEvent.caller;
                while (c) {
                    ev = c.arguments[0];
                    if (ev && Event == ev.constructor) {
                        break;
                    }
                    c = c.caller;
                }
            }
            return ev;
        }
    };
12、[“1”, “2”, “3”].map(parseInt) 答案是多少?
  • [1, NaN, NaN] 因为parseInt 需要两个参数(val, radix),其中radix 表示解析时用的基数。
  • map 传了3 个(element, index, array),对应的radix 不合法导致解析失败。
13、事件是?IE与火狐的事件机制有什么区别?如何阻止冒泡?
  • 我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被JavaScript 侦测到的行为。
  • 事件处理机制:IE是事件冒泡、Firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件;
  • ev.stopPropagation();(旧ie的方法ev.cancelBubble = true;)
14、什么是闭包(closure),为什么要用它?

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

闭包的特性

  • 函数内再嵌套函数
  • 内部函数可以引用外层的参数和变量
  • 参数和变量不会被垃圾回收机制回收
15、javascript 代码中的"use strict";是什么意思? 使用它区别是什么?
  • use strict是一种ECMAscript 5 添加的(严格)运行模式,这种模式使得Javascript 在更严格的条件下运行,

  • 使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为。

  • 默认支持的糟糕特性都会被禁用,比如不能用with,也不能在意外的情况下给全局变量赋值;

  • 全局变量的显示声明,函数必须声明在顶层,不允许在非函数代码块内声明函数,arguments.callee也不允许使用;

  • 消除代码运行的一些不安全之处,保证代码运行的安全,限制函数中的arguments修改,严格模式下的eval函数的行为和非严格模式的也不相同;

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

  • 为未来新版本的Javascript标准化做铺垫。

16、如何判断一个对象是否属于某个类?

使用instanceof (待完善)

 if(a instanceof Person){
 alert('yes');
}
17、new操作符具体干了什么呢?
  • 创建一个空对象,并且this 变量引用该对象,同时还继承了该函数的原型
  • 属性和方法被加入到this 引用的对象中。
  • 新创建的对象由this 所引用,并且最后隐式的返回this 。
var obj  = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
18、Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
一、hasOwnProperty

javaScript中hasOwnProperty函数方法是返回一个布尔值,指出一个对象是否具有指定名称的属性。此方法无法检查该对象的原型链中是否具有该属性;该属性必须是对象本身的一个成员。

二、使用方法

object.hasOwnProperty(proName)

  • 其中参数object是必选项。一个对象的实例。
  • proName是必选项。一个属性名称的字符串值。

如果object 具有指定名称的属性,那么JavaScript中hasOwnProperty函数方法返回true,反之则返回false。

19、JSON 的了解?
一、JSON(JavaScript Object Notation)
  • 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);
20、js延迟加载的方式有哪些?
一、defer
  • 脚本会延迟到页面解析完毕后再执行(只适用于外部脚本文件)
    <script type="text/javascript" defer></script>
二、async
  • 异步加载,不会阻塞页面其他内容(只适用于外部脚本文件)
    <script type="text/javascript" async></script>
三、动态创建DOM方式(用得最多)
varelement = document.createElement("script");  
element.src = "defer.js";  
document.body.appendChild(element);  
21、模块化开发怎么做?

立即执行函数,不暴露私有成员

var module1 = (function() {
    var _count = 0;
    var m1 = function() {      
        //...
    };    
    var m2 = function() {      
        //...
            };    
    return {      
        m1: m1,
        m2: m2    
    };  
})();
22、documen.write和innerHTML的区别
  • document.write只能重绘整个页面
  • innerHTML可以重绘页面的一部分
23、DOM操作——怎样添加、移除、移动、复制、创建和查找节点?
一、创建新节点
createDocumentFragment()    //创建一个DOM片段
createElement()   //创建一个具体的元素
createTextNode()   //创建一个文本节点
二、添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点
三、查找
 getElementsByTagName()    //通过标签名称
getElementsByName()    //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)
getElementById()    //通过元素Id,唯一性
24、.call() 和.apply() 的区别?

例子中用add 来替换sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4);

注意:js 中的函数其实是对象,函数名是对Function 对象的引用。

function add(a,b){ alert(a+b); }
function sub(a,b) { alert(a-b); }
add.call(sub,3,1);
add.apply(sub,[3,1]);

功能一样,但是传递参赛的方式不一样

25、数组和对象有哪些原生方法,列举一下?
push()  pop()  join()  indexOf()
26、JavaScript中的作用域?
  • 在js中每一个方法都试一个作用域,最大的作用域就是window对象,
  • 作用域中的变量和方法只能在当前作用域和当前作用域下的作用域使用
  • 外面的作用域不能访问里面作用域的变量和方法
  • js中查找变量的方式是,先在当前作用域查找,如果没有的话,就去上一级作用域中查找
27、浏览器本地存储
  • 在较高版本的浏览器中,js提供了sessionStorage和globalStorage。在HTML5中提供了localStorage来取代globalStorage。
  • html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage。
  • sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储
  • 而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。
28、那些操作会造成内存泄漏?
  • 使用闭包的时候如果在闭包变量中保存了大量的dom结构而且不去使用长期存在的时候,内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。

  • 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。

  • setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。

  • 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

29、页面重构怎么操作?

网站重构

  • 在不改变外部行为的前提下,简化结构、添加可读性,而在网站前端保持一致的行为。
  • 也就是说是在不改变UI的情况下,对网站进行优化,在扩展的同时保持一致的UI。
  • 对于传统的网站来说重构通常是:
  • 表格(table)布局改为DIV+CSS
  • 使网站前端兼容于现代浏览器(针对于不合规范的CSS、如对IE6有效的)
  • 对于移动平台的优化
  • 针对于SEO进行优化
  • 深层次的网站重构应该考虑的方面
  • 减少代码间的耦合
  • 让代码保持弹性
  • 严格按规范编写代码
  • 设计可扩展的API
  • 代替旧有的框架、语言(如VB)
  • 增强用户体验
  • 通常来说对于速度的优化也包含在重构中
  • 压缩JS、CSS、image等前端资源(通常是由服务器来解决)
  • 程序的性能优化(如数据读写)
  • 采用CDN来加速资源加载
  • 对于JS DOM的优化
  • HTTP服务器的文件缓存
30、列举IE与其他浏览器不一样的特性?

事件不同之处

  • 触发事件的元素被认为是目标(target)。而在IE 中,目标包含在event 对象的srcElement 属性;
    获取字符代码、如果按键代表一个字符(shift、ctrl、alt除外),IE 的keyCode 会返回字符代码(Unicode),DOM 中按键的代码和字符是分离的,要获取字符代码,需要使用charCode 属性;
    阻止某个事件的默认行为,IE 中阻止某个事件的默认行为,必须将returnValue 属性设置为false,Mozilla 中,需要调用preventDefault() 方法;
  • 停止事件冒泡,IE 中阻止事件进一步冒泡,需要设置cancelBubble 为true,Mozzilla 中,需要调用stopPropagation();
31、什么叫优雅降级和渐进增强?
一、优雅降级

Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会针对旧版本的IE进行降级处理了,使之在旧式浏览器上以某种形式降级体验却不至于完全不能用。
如:border-shadow

二、渐进增强

从被所有浏览器支持的基本功能开始,逐步地添加那些只有新版本浏览器才支持的功能,向页面增加不影响基础浏览器的额外样式和功能的。当浏览器支持时,它们会自动地呈现出来并发挥作用。
如:默认使用flash上传,但如果浏览器支持HTML5 的文件上传功能,则使用HTML5实现更好的体验

32、是否了解公钥加密和私钥加密。
  • 一般情况下是指私钥用于对数据进行签名,公钥用于对签名进行验证;
  • HTTP网站在浏览器端用公钥加密敏感数据,然后在服务器端再用私钥解密。
33、WEB应用从服务器主动推送Data到客户端有那些方式?
  • html5提供的Websocket
  • 不可见的iframe
  • WebSocket通过Flash
  • XHR长时间连接
  • XHR Multipart Streaming
  • <script>标签的长时间连接(可跨域)
34、对Node的优点和缺点提出了自己的看法?
一、优点
  • 因为Node是基于事件驱动和无阻塞的,所以非常适合处理并发请求,
    因此构建在Node上的代理服务器相比其他技术实现(如Ruby)的服务器表现要好得多。
    此外,与Node代理服务器交互的客户端代码是由javascript语言编写的,
    因此客户端和服务器端都用同一种语言编写,这是非常美妙的事情。
二、缺点
  • Node是一个相对新的开源项目,所以不太稳定,它总是一直在变,
    而且缺少足够多的第三方库支持。看起来,就像是Ruby/Rails当年的样子。
35、你有用过哪些前端性能优化的方法?
  • 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存,图片服务器。

  • 前端模板JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数

  • 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。

  • 当需要设置的样式很多时设置className而不是直接操作style。

  • 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。

  • 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。

  • 图片预加载,将样式表放在顶部,将脚本放在底部加上时间戳。

  • 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div+css布局慢。

对普通的网站有一个统一的思路,就是尽量向前端优化、减少数据库操作、减少磁盘IO。向前端优化指的是,在不影响功能和体验的情况下,能在浏览器执行的不要在服务端执行,能在缓存服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询。减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据库执行的操作尽可能的让你的程序完成(例如join查询),减少磁盘IO指尽量不使用文件系统作为缓存、减少读写文件次数等。程序优化永远要优化慢的部分,换语言是无法“优化”的。

36、你何时优化自己的代码?

一般都是功能完成后,不着急做其他功能的时候,会选择对以前实习的功能进行代码优化

37、== 和=== 有什么不同?

==是派生自=====回自动转化数据类型,===不会

38、Javascript垃圾回收方法
一、标记清除(mark and sweep)
  • 这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。
    垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
二、引用计数(reference counting)
  • 在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。

  • 在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的,也就是说只要涉及BOM及DOM就会出现循环引用问题。

39、用过哪些设计模式?
一、工厂模式:

主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位置防止代码重复。
工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。

function createObject(name,age,profession){//集中实例化的函数var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.profession = profession;
    obj.move = function () {
        return this.name + ' at ' + this.age + ' engaged in ' + this.profession;
    };
    return obj;
}
var test1 = createObject('trigkit4',22,'programmer');//第一个实例var test2 = createObject('mike',25,'engineer');//第二个实例
二、构造函数模式

使用构造函数的方法,即解决了重复实例化的问题,又解决了对象识别的问题,该模式与工厂模式的不同之处在于:

  • 构造函数方法没有显示的创建对象(new Object());
  • 直接将属性和方法赋值给this 对象;
  • 没有renturn 语句。
40、请你谈谈Cookie的弊端

cookie虽然在持久保存客户端数据提供了方便,分担了服务器存储的负担,但还是有很多局限性的。

一、每个特定的域名下最多生成20个cookie
  • IE6或更低版本最多20个cookie
  • IE7和之后的版本最后可以有50个cookie。
  • Firefox最多50个cookie
  • chrome和Safari没有做硬性限制
  • IE和Opera 会清理近期最少使用的cookie,Firefox会随机清理cookie。
  • cookie的最大大约为4096字节,为了兼容性,一般不能超过4095字节。
  • IE 提供了一种存储可以持久化用户数据,叫做userdata,从IE5.0就开始支持。每个数据最多128K,每个域名下最多1M。这个持久化数据放在缓存中,如果缓存没有清理,那么会一直存在。
二、优点:
  • 极高的扩展性和可用性
  • 通过良好的编程,控制保存在cookie中的session对象的大小。
  • 通过加密和安全传输技术(SSL),减少cookie被破解的可能性。
  • 只在cookie中存放不敏感数据,即使被盗也不会有重大损失。
  • 控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie。
三、缺点
  • Cookie`数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉.
  • 安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。
  • 有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。

41、cookie 和session 的区别:
  • cookie数据存放在客户的浏览器上,session数据放在服务器上。
  • cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
    考虑到安全应当使用session。
  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
    考虑到减轻服务器性能方面,应当使用COOKIE。
  • 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
  • 所以个人建议:

将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中

42、说说严格模式的限制
  • 严格模式主要有以下限制:
  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用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均不支持严格模式。

43、document.write()的用法
  • document.write()方法可以用在两个方面:页面载入过程中用实时脚本创建页面内容,以及用延时脚本创建本窗口或新窗口的内容。
  • document.write只能重绘整个页面。innerHTML可以重绘页面的一部分
44、编写一个方法求一个字符串的字节长度

假设:一个英文字符占用一个字节,一个中文字符占用两个字节

 function GetBytes(str){
 var len = str.length;
 var bytes = len;
for(var i=0; i<len; i++){
if (str.charCodeAt(i) > 255) bytes++;
 }
return bytes;
}
alert(GetBytes(“你好,as"));
45、说说你对MVC和MVVM的理解
一、MVC
  • View 传送指令到Controller
  • Controller 完成业务逻辑后,要求Model 改变状态
  • Model 将新的数据发送到View,用户得到反馈

所有通信都是单向的。

二、MVVM

Angular它采用双向绑定(data-binding):View的变动,自动反映在ViewModel,反之亦然。
组成部分Model、View、ViewModel

  • View:UI界面
  • ViewModel:它是View的抽象,负责View与Model之间信息转换,将View的Command传送到Model;
  • Model:数据访问层
46、说说网络分层里七层模型是哪七层

应用层:应用层、表示层、会话层(从上往下)(HTTP、FTP、SMTP、DNS)
传输层(TCP和UDP)
网络层(IP)
物理和数据链路层(以太网)
每一层的作用如下:
物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)
数据链路层:将比特组装成帧和点到点的传递(帧Frame)
网络层:负责数据包从源到宿的传递和网际互连(包PackeT)
传输层:提供端到端的可靠报文传递和错误恢复(段Segment)
会话层:建立、管理和终止会话(会话协议数据单元SPDU)
表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)
应用层:允许访问OSI环境的手段(应用协议数据单元APDU)

一、应用层

应用层:应用层、表示层、会话层(从上往下)(HTTP、FTP、SMTP、DNS)

  • 传输层(TCP和UDP)
  • 网络层(IP)
  • 物理和数据链路层(以太网)
二、物理和数据链路层

物理和数据链路层(以太网),每一层的作用如下:

  • 物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)
  • 数据链路层:将比特组装成帧和点到点的传递(帧Frame)
  • 网络层:负责数据包从源到宿的传递和网际互连(包PackeT)
  • 传输层:提供端到端的可靠报文传递和错误恢复(段Segment)
  • 会话层:建立、管理和终止会话(会话协议数据单元SPDU)
  • 表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)
  • 应用层:允许访问OSI环境的手段(应用协议数据单元APDU)
47、什么样的前端代码是好的

高复用低耦合,这样文件小,好维护,而且好扩展。

48、attribute和property的区别是什么?
  • attribute是dom元素在文档中作为html标签拥有的属性;
  • property就是dom元素在js中作为对象拥有的属性。

所以:

  • 对于html的标准属性来说,attribute和property是同步的,是会自动更新的,但是对于自定义的属性来说,他们是不同步的,
49、说说你对AMD和Commonjs的理解
  • CommonJS是服务器端模块的规范,Node.js采用了这个规范。CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是非同步加载模块,允许指定回调函数。

  • AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。

50、offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别
  • offsetWidth/offsetHeight返回值包含content + padding + border,效果与e.getBoundingClientRect()相同
  • clientWidth/clientHeight返回值只包含content + padding,如果有滚动条,也不包含滚动条
  • scrollWidth/scrollHeight返回值包含content + padding + 溢出内容的尺寸
51、focus/blur与focusin/focusout的区别与联系
  • focus/blur不冒泡,focusin/focusout冒泡
  • focus/blur兼容性好,focusin/focusout在除FireFox外的浏览器下都保持良好兼容性,如需使用事件托管,可考虑在FireFox下使用事件捕获elem.addEventListener(‘focus’, handler, true)

可获得焦点的元素

  • window
  • 链接被点击或键盘操作
  • 表单空间被点击或键盘操作
  • 设置tabindex属性的元素被点击或键盘操作
52、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表示移入时的来源元素

53、应用程序存储和离线web应用

HTML5新增应用程序缓存,允许web应用将应用程序自身保存到用户浏览器中,用户离线状态也能访问。

  • 为html元素设置manifest属性:,其中后缀名只是一个约定,真正识别方式是通过text/cache-manifest作为MIME类型。所以需要配置服务器保证设置正确
  • manifest文件首行为CACHE MANIFEST,其余就是要缓存的URL列表,每个一行,相对路径都相对于manifest文件的url。注释以#开头
  • url分为三种类型:CACHE:为默认类型。NETWORK:表示资源从不缓存。FALLBACK:每行包含两个url,第二个URL是指需要加载和存储在缓存中的资源,第一个URL是一个前缀。任何匹配该前缀的URL都不会缓存,如果从网络中载入这样的URL失败的话,就会用第二个URL指定的缓存资源来替代。以下是一个文件例子:
CACHE MANIFEST
CACHE:
myapp.html
myapp.css
myapp.js
FALLBACK:
videos/ offline_help.html
NETWORK:
cgi/
54、请用代码写出(今天是星期x)其中x表示当天是星期几,如果当天是星期一,输出应该是”今天是星期一”
var days = ['日','一','二','三','四','五','六'];
var date = new Date();
console.log('今天是星期' + days[date.getDay()]);
55、下面这段代码想要循环延时输出结果0 1 2 3 4,请问输出结果是否正确,如果不正确,请说明为什么,并修改循环内的代码使其输出正确结果
for (var i = 0; i < 5; ++i) {
(function (i) {
setTimeout(function () {
console.log(i + ' ');
}, 100);
}(i));
}

不能输出正确结果,因为循环中setTimeout接受的参数函数通过闭包访问变量i。javascript运行环境为单线程,setTimeout注册的函数需要等待线程空闲才能执行,此时for循环已经结束,i值为5.五个定时输出都是5 修改方法:将setTimeout放在函数立即调用表达式中,将i值作为参数传递给包裹函数,创建新闭包

56、如何编写高性能的Javascript?
  • 使用 DocumentFragment 优化多次 append
  • 通过模板元素 clone ,替代 createElement
  • 使用一次 innerHTML 赋值代替构建 dom 元素
  • 使用 firstChild 和 nextSibling 代替 childNodes 遍历 dom 元素
  • 使用 Array 做为 StringBuffer ,代替字符串拼接的操作
  • 将循环控制量保存到局部变量
  • 顺序无关的遍历时,用 while 替代 for
  • 将条件分支,按可能性顺序从高到低排列
  • 在同一条件子的多( >2 )条件分支时,使用 switch 优于 if 使用三目运算符替代条件分支
  • 需要不断执行的时候,优先考虑使用 setInterval
57、eval是做什么的?
一、作用

字符串参数解析成JS代码并运行,并返回执行的结果

let result = eval("2*3+4");
console.log(result);    //10
二、eval的作用域

在它所有的范围内容有效

function func() {
    eval(num = 3)
    console.log(2 + num);   //5
};

func()
三、注意

尽量避免使用eval,存在安全问题,非常消耗性能 —— ⑴ 一次解析成js语句 ⑵ 一次执行

58、你如何从浏览器的URL 中获取查询字符串参数。

http://192.168.1.140:5002/del.html?id=3&&name=tom

一、普通版
function getString() {
    //取得查询字符串并去掉开头的问号
    var str = (location.search.length > 0 ? location.search.substring(1) : "");
    var args = {}; //保存数据的对象
    items = str.length ? str.split('&') : []; //取得每一项
    var item = null;
    var name = null;
    var value = null;
    for (var i = 0; i < items.length; i++) {
        item = items[i].split('=');
        name = decodeURIComponent(item[0]);
        value = decodeURIComponent(item[1]);
        if (name.length) {
            args[name] = value;
        }
    }
    return args;
}

console.log(getString());   //{id:3;name:"tom"}
二、正则版
function getUrlPara(name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
    var r = window.location.search.substr(1).match(reg);
    if (r != null) return (r[2]);
    return null;
}
console.log(getUrlPara("id"));  //3
59、修改指定路径参数(正则版)
let url = window.location.href;
let pageParam = "default";
let result = changeURLArg(url, "id", pageParam)
console.log(result)

function changeURLArg(url, arg, arg_val) {
    var pattern = arg + '=([^&]*)';
    var replaceText = arg + '=' + arg_val;
    if (url.match(pattern)) {
        var tmp = '/(' + arg + '=)([^&]*)/gi';
        tmp = url.replace(eval(tmp), replaceText);
        return tmp;
    } else {
        if (url.match('[\?]')) {
            return url + '&' + replaceText;
        } else {
            return url + '?' + replaceText;
        }
    }
}
60、代替eval计算字符串:
function evalPro(str) {
    var Fn = Function;
    return new Fn('return ' + str)();
}

function evalPro(param = "1+23") {
    let result = new Function("return " + param)();
    return result
}
console.log(evalPro());   //24

标签:前端面试,JavaScript


更多演示案例,查看 案例演示


欢迎评论留言!

  • 87
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 253
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 253
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人间小美味695

您的鼓励是我创作的动力,感谢!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值