29.AMD,CMD模块化
模块化的开发方式可以提高代码复用率,方便进行代码的管理。通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数。目前流行的js模块化规范有CommonJS、AMD、CMD以及ES6的模块系统
1、AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
2、CMD推崇就近依赖,只有在用到某个模块的时候再去require
这种区别各有优劣,只是语法上的差距,而且requireJS和SeaJS都支持对方的写法
AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同
30.报表绘图类的框架
highcharts http://www.highcharts.com/
jscharts http://www.jscharts.com/
AdminLTE http://adminlte.la998.com/
31.库和插件的源代码
库和框架都是一种有别于软件、面向程序开发者的产品形式。
库是将代码集合成的一个产品,供程序员调用。面向对象的代码组织形式而成的库也叫 类库。 框架则是为解决一个(一类)问题而开发的产品,框架用户一般只需要使用框架提供的类 或函数,即可实现全部功能。
32.函数柯里化是什么 ?
柯里化(英语:Currying),又称为部分求值,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回一个新的函数的技术,新函数接受余下参数并返回运算结果。
具体内容见 https://juejin.im/entry/58b316d78d6d810058678579
33.哪些情况下会造成内存泄漏 ?
1)意外的全局变量引起的内存泄露 ```javascript function leak () { leak="xxx"; //leak成为一个全局变量,不会被回收 相当于 window.leak = 'XXX' } ``` 2. 闭包可以维持函数内局部变量,使其得不到释放。 3. 没有清理的DOM元素引用 4. 被遗忘的定时器或者回调
34.性能优化 ?
1. 定义局部变量.查找局部变量比全局变量要快。 2. 不滥用闭包。 3. 合并js文件,减少http请求 4. 避免使用for-in循环 5. 尽量不用with,eval语句,try-catch的catch子句要谨慎使用
35.工作中闭包的使用案例?使用过什么闭包工具库嘛
1. 闭包经典使用场景一:通过循环给页面上多个dom节点绑定事件 ```javascript <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <button>Button0</button> <button>Button1</button> <button>Button2</button> <button>Button3</button> <button>Button4</button> </body> </html> for(var i = 0, len = btns.length; i < len; i++) { (function(i) { btns[i].onclick = function() { alert(i); } }(i)) } ``` 2. 封装变量 闭包可以将一些不希望暴露在全局的变量封装成“私有变量”。 3. 闭包使用场景三:延续局部变量的寿命 闭包工具库:???
36.301 302如何重定向 ?
301 redirect: 301 代表永久性转移(Permanently Moved) 302 redirect: 302 代表暂时性转移(Temporarily Moved ) 详细来说,301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。他们的不同在于。301表示旧地址A的资源已经被永久地移除(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。
37.暂时性死区 ?
举例: ```javascript console.log (a) //由于变量提升,输出undefined var a ``` ```javascript console.log(a) //报错 ReferenceError: a is not defined let a ``` ES6规定,let/const 命令会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。 总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。 这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ)。
38.堆和栈
栈(stack):为自动分配的内存空间,他由系统自动释放。存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的,所以可以直接访问。基本的数据类型放在栈中
堆(heap):则是动态分配的内存,大小不定也不会自动释放。引用类型(object)是存放在堆内存中的,变量实际上是一个存放在栈内存的指针,这个指针指向堆内存中的地址。每个空间大小不一样,要根据情况进行特定的分配。
39.箭头函数的this指向
- 箭头函数默认不会使用自己的this,而是会和外层的this保持一致,最外层的this就是window对象。在多层对像嵌套里箭头函数里this是和最最外层保持一致的
40.深拷贝和浅拷贝的区别
- 浅拷贝:只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存
- 深拷贝:复制并创建一个一模一样的对象,不共享内存,修改新对象,旧对象保持不变。
41.手写一个promise,采用es5的方面。promise的源码理解
var fn=function(resolve, reject){ console.log('begin to execute!'); var number=Math.random(); if(number<=0.5){ resolve('less than 0.5'); }else{ reject('greater than 0.5'); } } var p=new Promise(fn); p.then(function(data){ console.log('resolve: ', data); }, function(data){ console.log('reject: ', data); }) 对promise源码的理解: 当我们运行 var p=new Promise(fn) 这条语句的时候,fn函数就已经执行了,然而,p.then这个方法是在后面才定义了resolve和reject,那么为何fn函数能够知道resolve和reject函数是什么呢?换句话说,resolve和reject函数是如何回到过去,出现在先执行的fn函数当中的呢?要解决这个问题,主要运用的就是setTimeout这个方法,来延迟fn当中resolve和reject的执行。我们知道js是单线程+消息队列,必须等主线程代码执行完毕才能开始执行消息队列当中的代码。因此,会首先执行then这个方法,给里面两个参数赋值。 加入状态:pending, resolved, rejected 在Promise规范当中,规定Promise只能从初始pending状态变到resolved或者rejected状态,是单向变化的,也就是说执行了resolve就不会再执行reject,反之亦然。并在必要的地方进行判断,防止重复执行。 function MyPromise(fn) { this.value; this.status = 'pending'; this.resolveFunc = function() {}; this.rejectFunc = function() {}; fn(this.resolve.bind(this), this.reject.bind(this)); } MyPromise.prototype.resolve = function(val) { var self = this; if (this.status == 'pending') { //判断状态 this.status = 'resolved'; this.value=val; setTimeout(function() { self.resolveFunc(self.value); }, 0); } } MyPromise.prototype.reject = function(val) { //判断状态 var self = this; if (this.status == 'pending') { this.status = 'rejected'; this.value=val; setTimeout(function() { self.rejectFunc(self.value); }, 0); } } MyPromise.prototype.then = function(resolveFunc, rejectFunc) { this.resolveFunc = resolveFunc; this.rejectFunc = rejectFunc; } 链式调用: 要实现链式调用,then方法的返回值也必须是一个Promise对象,这样才能再次在后面调用then。
42.async与promise的区别:
在函数前有一个关键字async,await关键字只能在使用async定义的函数中使用。任何一个async函数都会隐式返回一个promise,并且promise resolve 的值就是 return 返回的值
不能在函数开头使用await
Async 函数的实现最简洁,最符合语义,几乎没有语义不相关的代码。
Promise 的写法比回调函数的写法大大改进,但是一眼看上去,代码完全都是 Promise 的 API(then、catch等等),操作本身的语义反而不容易看出来。