宫鹏面试题解析

246 阅读11分钟

请简述HTML5离线存储的方法和实现方式

在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。 原理:HTML5的离线存储是基于一个新建的.appcache文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像cookie一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示。

如何使用: 1、页面头部像下面一样加入一个manifest的属性; 2、在cache.manifest文件的编写离线存储的资源; CACHE MANIFEST 必须的存储类型 v0.11 CACHE: 要缓存的文件 js/app.js css/style.css NETWORK: 不需要缓存的文件 resourse/logo.png FALLBACK: offline.html 3、在离线状态时,操作window.applicationCache进行需求实现。

cookie sessionStorage localStorage的区别

相同点 都存储在客户端。

不同点 1.存储大小

cookie数据大小不能超过4k。 sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。

2.有效时间

localStorage:存储持久数据,浏览器关闭后数据不丢失除非主动删除数据。 sessionStorage:数据在当前浏览器窗口关闭后自动删除。 cookie:设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。

3.数据与服务器之间的交互方式

cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端 sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。

什么是防抖和节流,有什么区别?如何实现?

防抖 触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间; 思路: 每次触发事件时都取消之前的延时调用方法:

function debounce(fn) {
    let timeout = null; // 创建一个标记用来存放定时器的返回值
    return function () {
    clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
    timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
        fn.apply(this, arguments);
    }, 500);
    };
}
function sayHi() {
    console.log('防抖成功');
}

var inp = document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi)); // 防抖

节流 高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。 思路: 每次触发事件时都判断当前是否有等待执行的延时函数

function throttle(fn) {
    let canRun = true; // 通过闭包保存一个标记
    return function () {
        if (!canRun) return; // 在函数开头判断标记是否为 true,不为 truereturn
        canRun = false; // 立即设置为 false
        setTimeout(() => { // 将外部传入的函数的执行放在 setTimeout 中
            fn.apply(this, arguments);
            // 最后在 setTimeout 执行完毕后再把标记设置为 true(关键) 表示可以执行下一次循环了。当定时器没有执行的时候标记永远是 false,在开头被 return 掉
            canRun = true;
        }, 500);
    };
}
function sayHi(e) {
    console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi));

Set map WeakSet 和 WeakMap的区别

set (集合) 1.成员不能重复 2.只有健值,没有健名,有点类似数组。 3.可以遍历,方法有add, delete,has

WeakSet 1.成员都是对象 2.成员都是弱引用,随时可以消失。 可以用来保存DOM节点,不容易造成内存泄漏 3.不能遍历,方法有add, delete,has

map (字典) 1.本质上是健值对的集合,类似集合 2.可以遍历,方法很多,可以干跟各种数据格式转换

weakmap 1.直接受对象作为健名(null除外),不接受其他类型的值作为健名 2.健名所指向的对象,不计入垃圾回收机制 3.不能遍历,方法同get,set,has,delete

ES5/ES6继承除了写法之外还有什么区别?

ES5的继承是通过prototype或构造函数机制来实现。

ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.apply(this))。

ES6的继承机制实质上是先创建父类的实例对象this(所以必须先调用父类的super()方法),然后再用子类的构造函数修改this。具体为ES6通过class关键字定义类,里面有构造方法,类之间通过extends关键字实现继承。子类必须在constructor方法中调用super方法,否则新建实例报错。因为子类没有自己的this对象,而是继承了父类的this对象,然后对其调用。如果不调用super方法,子类得不到this对象。

注意:super关键字指代父类的实例,即父类的this对象。在子类构造函数中,调用super后,才可使用this关键字,否则报错。

说几条写javascript的基本规范

1.减少全局污染 我们都知道javascript使用的是function来管理自己的作用域的,一个定义在函数内的变量对外界是不可见的。这有点类似于其他语言的私有变量。对于javascript的执行环境来说,一般都有一个全局变量,在所有函数外可以用this来指引,例如在浏览器断是window,但是对于当过多的在全局环境下定义变量会造成各种各样的问题,过多的全局变量放在堆栈里还会造成内存的浪费。 2.变量名的提升,应该在函数内部中所有使用var声明的变量都会提升到函数体头部。以免造成不必要的错误。 3.for循环

我们经常会把for()循环写成这种形式的。 for(var i=0,;i<myarray.length;i++)其实呢dom遍历是需要时间的,如果我们在数据很多的情况下也这样子写的话,这样子网页的性能就会变差,所以我们应该重复循环使用的是一开始遍历得到的结果myarray.length,把它保存在一个变量中,这样子我们就可以不用循环遍历再次进行操作了。

for(var i=0,max=myarray.length;i<max;i++) 4.用“===”取代"==",前者是严格相等的意思,连数据类型也是需要相比较的,而后者提前会进行隐式的类型转换。 5.花括号{} 我们如果使用了for循环或者是if语句的话,我们都应该使用{},即使是if后面的语句只有一行,我们也应该要使用{}。 6.命名规则 构造器函数首字母大写,如function Person(){} 常用变量用大写字母PI。 7.写注释。 8.不要在同一个行内声明多个变量。 9.Switch语句中必须带有default分支,

简述如何实现数组的随机排序

var arr = [1,2,3,4,5,6,7,8,9]
function randomsort1 (arr) {
    for (let i = 0, len = arr.length; i < len; i++) {
        const ran = parseInt(Math.random() * len)
        const temp = arr[ran]
        arr[ran] = arr[i]
        arr[i] = temp
    }
    return arr
}
function randomsort2 (arr) {
    const newarr = []
    while (arr.length) {
        const ran = parseInt(Math.random() * arr.length)
        newarr.push(arr[ran])
        arr.splice(ran, 1)
    }
    return newarr
}
function randomsort3 (arr) {
    return arr.sort(() => Math.random() - 0.5)
}

请简述对this的指向的理解

this表示当前对象,this的指向是根据调用的上下文来决定的,默认指向window对象,指向window对象时可以省略不写,例如:this.alert() <=> window.alert()<=> alert(); 调用的上下文环境包括全局和局部

全局环境 全局环境就是在里面,这里的this始终指向的是window对象,

局部环境 1)在全局作用域下直接调用函数,this指向window 2)对象函数调用,哪个对象调用就指向哪个对象 3)使用 new 实例化对象,在构造函数中的this指向实例化对象。 4)使用call或apply改变this的指向

什么是eval

①它的功能是把对应的字符串解析成JS代码并运行; ②应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)。 ③由JSON字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')');

什么是闭包(closure)? 闭包的作用

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

闭包的特性: 1.函数内再嵌套函数 2.内部函数可以引用外层的参数和变量 3.参数和变量不会被垃圾回收机制回收

闭包的用途: 1、读取函数内部的变量 2、让这些变量的值始终保持在内存中。不会再f1调用后被自动清除。 3、方便调用上下文的局部变量。利于代码封装。 原因:f1是f2的父函数,f2被赋给了一个全局变量,f2始终存在内存中,f2的存在依赖f1,因此f1也始终存在内存中,不会在调用结束后,被垃圾回收机制回收。

闭包的缺点: 1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。 2、闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

如何解决跨越问题

javascript解决跨越(同源策略)的三种方案 在某些情况下,同源策略就显得太过严格了,下面是三种不严格的同源策略

domain

同源策略给那些使用多个子域的大站点带来了一些问题,例如,来自home.example.com的文档里的脚本想要合法的读取从developer.example.com载入的文档的属性,或者来自orders.example.com的脚本可能需要读catalog.example.com上文档的属性。为了支持这种类型的多域名站点,可以使用Document对象的domain属性。在默认情况下,属性domain存放的是载入文档的服务器的主机名。可以设置这一属性,不过使用的字符串必须具有有效的域前缀或它本身。因此如果一个domain属性的初始值是字符串“home.exaple.com” ,就可以把他设置为字符串“example.com”,但不能设置为“home.example”。另外。domain值中必须有一个点号,不能把它设置为“com”或其他顶级域名。

如果两个窗口(或窗体)包含的脚本把domain设置为相同的值,那么这两窗口就不再受同源策略的约束,它们可以相互读取对方的属性。例如,从order.example.com和catalog.example.com载入的文档中的脚本可以把它们的document.domain属性设置为“example.com”,这样一来这些文档就有了同源性,可以互相读取属性。

跨域资源共享CORS

跨域资源共享(Cross-Origin Resource Sharing,参见http://www.w3.org/TR/cors)。这个标准草案用新的“Origin:”请求头和新的Access-Control-Allow-Origin响应头来扩展http。它允许服务器用头信息显式的列出源,或使用通配符来匹配所有的源并允许由任意地址请求文件。类似Firefox和Safari的浏览器可以使用这种新的头信息来允许跨越http请求,这样XMLHttpRequest就不会被同源策略限制了。

跨文档消息 postMessage()

跨文档消息(cross-document messaging),允许来自一个文档的脚本可以传递文本消息到另一个文档里的脚本,而不管脚本的来源是否不同。调用Window对象上的postMessage()方法,可以异步传递消息事件(可以用onmessage事件句处理程序函数来处理它)到窗口的文档里,一个文档里的脚本还是不能调用在其他文档里的方法和读取属性,但他们可以用这种消息传递技术实现安全的通信。

如何封装微信小程序的数据请求?

用promise封装