1. 对 ajax 的理解,实现一个 ajax 请求 ```typescript // method GET POST function ajax(url, method, options) { let xhr = new XMLHttpRequest() xhr.open(method, url, true) xhr.opreadystatechange = function () { if (this.readyState !== 4) return if (this.status === 200) { handle(this.response) } else { console.error(this.statusText) } } xhr.onerror = function () { console.error(this.statusText) } xhr.responseType = ‘json’ for(let head in options) { xhr.setRequestHeader(head, options[head]) } xhr.send(null) }

    // Promise 处理 function ajaxPromise(url, method, options) { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest() xhr.open(method, url, true) xhr.opreadystatechange = function () { if (this.readyState !== 4) return if (this.status === 200) { resolve(this.response) } else { reject(new Error(this.statusText)) } } xhr.onerror = function () { reject(new Error(this.statusText)) } xhr.responseType = ‘json’ for(let head in options) { xhr.setRequestHeader(head, options[head]) } xhr.send(null) }) }

    1. 17. JavaScript 为什么要变量提升?导致了什么问题
    2. - 表现:当变量在声明前就可以访问到而不报错,这里的现象就是变量提升
    3. - 造成变量提升的本质原因,是因为 **JS 代码存在解析执行上下文的过程 **。当访问一个变量时,会到当前执行上下文的作用域链中去查找,而作用域链会包含当前所有函数形参、所有的函数、所有的变量声明,这在代码解析时就已经创建好了
    4. - 解析阶段:JS 检查语法,对函数进行预编译。解析会创建全局执行上下文,把函数、变量等都拿出来,变量先初始化为 undefined,函数先声明好可以使用
    5. - 执行阶段:按照代码顺序依次执行
    6. - 为什么会进行变量提升?
    7. - 提高性能,提前解析会进行语法检查和预编译,能够提前报错、处理一些固定的变量。比如可以提前解析函数并为函数分配栈、提前为变量分配内存空间。解析过程还会为函数生成**预编译代码**,预编译时会统计变量和函数、代码压缩、取出注释空白等等
    8. - 容错性更好,访问未定义的变量不会直接报错
    9. - 总结
    10. - 解析和预编译的过程中,变量提升可以提高性能,比如让函数可以提前为变量分配栈空间
    11. - 变量提升可以提高 JS 代码的容错性,使用一些不规范的代码也可以正常执行
    12. - 变量提升也会导致一些结构或者代码上的问题
    13. - 现在一般建议要么就将变量提升到代码顶端,要么直接使用 ES6 let const 变量
    14. ```typescript
    15. var tmp = new Date();
    16. function fn(){
    17. console.log(tmp);
    18. if(false){
    19. var tmp = 'hello world';
    20. }
    21. }
    22. fn(); // undefined,tmp 被内层的 tmp 覆盖了
    1. 什么是尾调用?使用尾调用有什么好处
    • 尾调用指的是函数的最后一步调用另外一个函数。代码的执行是基于执行栈的,所以当一个函数调用另一个函数时,会保留当前的执行上下文,然后新建另外一个执行上下文加入栈中。使用尾调用,因为已经是函数的最后一步,因此不需要保留当前的执行上下文,从而节省内存,这就是尾调用优化。
    • 但是 ES6 的尾调用优化只在严格模式下开启,正常模式无效
    1. ES6 模块与 CommonJS 模块有什么异同?
    • ES6 Module 是静态引用,是对模块的引用,ES6 Module 只存只读,不能改变值,即指针的指向
    • CommonJS 是动态引用,是对模块的浅拷贝。
    • import 的接口是 read-only 只读状态。不能修改其变量值,即不能修改其变量的指针指向,但可以改变变量内部指针指向,可以对 CommonJS 重新赋值。但是对 ES6 Module 赋值会编译报错
    • ES6Module 和 CommonJS 的共同点:都可以对引入的对象进行赋值。即对对象内部属性的值进行改变。但是不会修改到文件当中,只能修改内存中读取到的。也就是说如果还有其他的文件读取,那么读取到的还是初始值