- 闭包是指能够访问另一个函数作用域中的变量的一个函数。 在js中,只有函数内部的子函数才能访问局部变量, 所以闭包可以理解成 “定义在一个函数内部的函数”。
闭包的作用
- 利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部,让外部函数可以访问到内部函数的变量和方法
闭包的优点
- 正常的函数,在执行完之后,函数里面声明的变量会被垃圾回收机制处理掉。但是形成闭包的函数在执行之后,不会被回收,依旧存在内存中。
闭包的缺点
- 因为变量不会被回收,所以内存中一直存在,耗费内存。
- 同步任务是指在主线程上排队执行的任务,
只有前一个任务执行完毕,才能继续执行下一个任务。
- 异步任务指的是,不进入主线程、而进入"任务队列"的任务,只有等主线程任务执行完毕,"任务队列"的任务才会进入主线程执行。
异步任务分为 宏任务 和 微任务
|
|---|
| 9.浏览器为什么要阻止跨域请求?如何解决跨域?每次跨域请求会达到服务端吗? |
-
浏览器阻止跨域请求的原因是因为"同源政策" , "同源政策"主要解决浏览器的安全问题,"同源"是 协议、域名 和 端口都相同,非同源是 协议 域名 和 端口 只要有一个不同都是非同源,就会有跨域问题
-
解决跨域的方法有很多种
- 使用jsonp跨域
- postMessage跨域
- 跨域资源共享(CORS)
- nodejs中间件代理跨域( (用的最多)通过中间件进行转发到非同源地址,请求的还是同源地址)
- WebSocket协议跨域
-
每次的跨域请求都会正常发出,服务端也会正常返回,但是被浏览器拦截了,所以跨域请求会到达服务端
1. 理解
- 定义:程序中已在堆中分配的内存,因为某种原因未释放或者无法释放的问题
- 简单理解: 无用的内存还在占用,得不到释放和归还,比较严重的时候,无用的内存还会增加,从而导致整个系统卡顿,甚至崩溃。
2. 生命周期
1. 分配期
分配所需要的内存,在js中,是自动分配的
2. 使用期
使用分配的内存,就是读写变量或者对象的属性值
3. 释放期
不需要时将该内存释放,js会自动释放(除了闭包和一些bug以外)
内存泄漏就是出现在这个时期,内存没有被释放导致的
3. 可能出现内存泄漏的原因
1. 意外的全局变量
2. DOM元素清空时,还存在引用
3. 闭包
4. 遗忘的定时器
|
|---|
| 11.Token一般存放在哪里? Token放在 cookie, sessionStorage 和 localStorage 中有什么区别? |
W3C 中定义事件的发生经历三个阶段
- 捕获阶段
- 目标阶段
- 冒泡阶段
- 阻止冒泡:在 W3c 中,使用 stopPropagation()方法
- 创建一个空对象,并且把 this 指向这个对象,同时还继承了该对象的原型
- 属性和方法被加入到 this 引用的对象中
- 不会进行函数提升
- 没有自己的 this,this指向的是所在作用域指向的对象
- 不能使用 new 关键字
- 不可以使用 arguments 对象
|
|---|
| 15.JavaScript 原型,原型链 ? 有什么特点? |
原型
- 原型分为隐式原型(__proto__) 和 显式原型(prototype),每个对象都有它的隐式原型(__proto__),指向它对应构造函数的显式原型(prototype)
- 无论何时,只要创建一个函数,就会为这个函数添加一个 prototype 属性,这个属性就指向原型对象__JavaScript高级程序设计(第四版)p225
- 构造函数的 prototype 指向原型对象,原型对象有一个 constructor 属性指回构造函数,每个构造函数生成的实例对象都有一个 __proto__ 属性,这个属性也指向原型对象。
原型链
- 每个对象都有 __proto__ 属性,这个属性指向原型对象,当想访问对象的一个属性时,如果这个对象本身没有这个属性就会通过 __proto__属性 查找,原型对象也是对象,每个对象又有自己的 __proto__ 属性,所以就会一直这样查找上去,直到找到这个属性,这就是原型链的概念。
- 原型链就是对象沿着 __proto__ 这条链逐步向上搜索,最顶层是 Object,Object 的 __proto__ 是 null。
- 是 js 中常用绑定事件的常技巧。“事件代理”是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是 DOM 元素的事件冒泡。使用事件委托的好处是可以提高性能。
- 可以大量节省内存占用,减少事件注册,当新增子对象时无需再次对其绑定。
JSON 字符串转换为 JSON 对象
let obj = JSON.parse(str)
JSON 对象转换为 JSON 字符串
let obj = JSON.stringify(str)
作用域
- 函数在定义时会创建一个 AO对象,就是作用域
- 规定变量和函数的可使用范围称为 作用域
作用域链
- 作用域链会被保存到一个隐式属性 [[ scope ]] 中去,这个属性是我们用户访问不到的,但的的确确是存在的 是让js引擎来访问的 里面存储的就是作用域链 作用域就是代码执行之前产生的 AO 和 GO, 作用域链就是 AO 和 GO 的集合
- 每个函数都有一个作用域链,查找变量或方法时,会先从函数作用域逐层查找最后到全局作用域查找,这些作用域的集合称为作用域链。
- 浅拷贝:
如果拷贝的是基本数据类型相当于直接拷贝它的值,修改值互不影响
如果拷贝的是引用数据类型,拷贝的就是指向堆内存里面这个对象的内存地址,如果修改了其中一个对象的数据,那么另一个对象也会受到影响,因为内存地址指向堆里面同一块内存
常用 es6 0bject.assign() 实现
- 深拷贝:
深拷贝是将一个对象完整的独立拷贝一份出来,然后在堆内存中开辟一块新的内存块存储,所以不会互相影响
常用 es6扩展运算符 递归 Array.concat() 实现
防抖:高频的触发事件,规定时间内触发会被清除,只有当超过规定时间触发,然后执行最后一次事件
节流:高频的触发事件,限制触发次数,规定时间内只能触发一次
- 2开头的表示请求成功
- 3开头的表示重定向
- 4开头表示客户端错误
- 400表示请求报文中存在语法错误
- 403常见的跨域
- 404请求资源不存在
- 5开头表示服务器端错误
- let、const: 声明变量和常量
- 模板字符串:增强版的字符串,用反引号标识,嵌入变量只需要放在
${}中
- 箭头函数:ES6中函数定义不再使用关键字function(),而是利用了()=>来进行定义
- 解构赋值:按照类型的不同有不同的方式提取值,赋值
- Symbol:新增的基本数据类型,特点就是里面的值唯一
- Set 和 Map 数据结构
- 展开运算符(…): 可以将数组或对象里面的值展开, 还可以将 Set 数据结构转换为数组
for...of 循环: 可以遍历数组对象以及 Set 和 Map 数据结构
- class 类:通过
extends 实现继承
- promise、(async/await): 都是用来解决异步编程的方案
10.proxy:代理对象,直接监听对象的变化,然后触发相应的逻辑
- Promise 是
es6 引入解决异步编程问题的解决方案
- Promise 有三种状态:pending(进行中)、resolve(已完成)、reject(已失败)
- 当 Promise 的状态由 pending 转变为 resolved 或 reject 时,会执行相应的回调, 一旦从 pending 状态变成为其他状态就不能再更改状态了
- 可以链式调用,解决回调地狱的问题
|
|---|
| 28. Promise.all() 和 Promise.race() |
Promise.all()
Promise.all() 的作用是接收一组异步任务,然后并行执行任务,等所有任务执行完之后再执行回调
Promise.all() 传入一组 Promise 数组,只有当所有的 Promise 状态都成功才返回成功,只要有一个失败就返回失败的 Promise 状态
Promise.race()
Promise.race() 的作用是接收一组异步任务,然后并行执行任务,只留取第一个完成的任务,其他任务任然会执行,只不过执行结果会被抛弃
Promise.race() 传入一个 Promise 数组,返回的结果由第一个执行完成的 Promise对象 的结果来决定
|
|---|
| 29. 怎么让一个函数无论promise对象成功和失败都能被调用? |
Promise.finally() finally 方法用于不管 Promise 的状态变为什么,都会执行它内部的函数
|
|---|
| 30. ajax 的作用 和 优缺点 (ajax整理的不多就一起放这里面了) |
优点
- 实现页面局部刷新,在不刷新整个页面的情况下与服务器通信
- 分担一部分后端的工作,减少服务器压力
缺点
- 对 seo 的支持比较弱
- ajax 不支持浏览器的返回按钮
1. 创建 ajax 对象
const ajax = new XMLHttpRequest();
2. 创建 ajax 请求 (设置请求的方法和请求地址) open
ajax.open('get', 'http://localhost:8080/server?a=100&b=200');
3. 发送请求 send
ajax.send();
4. 处理服务器端返回的结果 onreadystatechange事件
readystate:五个值 0 1 2 3 4,为4的时候代表数据已经接收完成
status:状态码 200 为成功
if(ajax.readystate === 4 && ajax.status >= 200 && ajax.status < 300) {
表示成功,可以写相应的逻辑了
}
- 原生 ajax 可以通过 XMLHttpRequest 对象上的 abort 方法中断 ajax 请求;
- 应用场景:文件上传
- 两者都可以用于遍历数组,只不过
for-in遍历的是数组元素的索引 (index), 而for-of遍历的是数组元素的值
for-in 可以遍历普通对象,获取的是对象的键名。 for-of 不可以遍历普通对象
for-in 不可以遍历Set/Map for-of 可以遍历Set/Map
typeof常用于判断基本数据类型,因为对象、数组和Null都返回的Object
console.log(typeof '温情');
console.log(typeof 111);
console.log(typeof true);
console.log(typeof undefined);
console.log(typeof function () { });
console.log(typeof {});
console.log(typeof [1,2,3]);
console.log(typeof null);
instanceof用于判断引用数据类型,检测构造函数的prototype属性是否出现在某个实例对象的原型链上,有则返回true,否则返回false,就是判断对象属于什么类型;
let arr = [];
console.log(arr instanceof Array);
console.log(arr instanceof Object);
let obj = {};
console.log(obj instanceof Array);
console.log(obj instanceof Object);
let date = new Date();
console.log(date instanceof Date);
console.log(date instanceof Object);
console.log(date instanceof Array);
Object.prototype.toString.call()返回一个“[object XXX]”格式的字符串,XXX就是具体的数据类型
function getType(value) {
if(typeof value !== 'object') {
return typeof value;
} else {
return Object.prototype.toString.call(value).split(' ')[1].slice(0, -1);
}
};
console.log( getType() );
console.log( getType(null) );
console.log( getType(123) );
console.log( getType('温情') );
console.log( getType({}) );
console.log( getType([]) );
console.log( getType(new Date) );
console.log( getType(new RegExp) );
console.log( getType(new Function) );
push 向数组后面添加元素
concat 数组连接、合并
length 数组元素的长度
join() 将数组元素连接起来构成一个字符串,括号里面代表用什么分割
pop 移除数组的最后一个元素,返回值是被移除的元素
shift 移除数组的第一个元素,返回值是被移除的元素
unshift 向数组的开头添加一个或多个元素,返回值是加了之后新的长度
sort 对数组的元素进行排序,并返回数组
reverse 将数组中元素的位置颠倒,并返回该数组。
slice(begib, end) 返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的(包括 begin,不包括end)。原始数组不会被改变。
splice(start, deleteItem, items) 通过删除或替换现有元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
indexOf 返回在数组中可以找到一个给定元素的第一个索引(下标),如果不存在,则返回-1
lastIndexOf(searchEle, fromIndex) 返回指定元素在数组中的最后一个的索引(下标),如果不存在则返回 -1。从数组的后面向前查找,第二个参数可选,如果有第二个参数从 fromIndex 处开始往前找。
- DOM:文档对象模型,就是把 文档 当做一个对象,顶级对象是
document, dom主要是操作页面元素。
- BOM: 浏览器对象模型,把 浏览器 当做一个对象,顶级对象是
window, bom主要是控制浏览器窗口交互的一些对象,除了window还有history,navigator,location
|
|---|
| 37. typeof null的结果是什么,为什么? |
- 结果是object,因为对象在底层是用二进制表示的,在js中二进制前三位都为0的话会被判定为object类型,null为空,二进制表示全为0,所以就被判定为object了
- commonJs主要使用
require()和module.exports来引入和导出各种值
- es6模块主要是
import和export来引入和导出各种值
- commonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用;
- 关于模块顶层的this指向问题,在commonJS顶层,this指向当前模块; 而在ES6模块中,this指向
undefined;
- Object.prototype.toString.call();
- 对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
function getType(value) {
if(typeof value !== 'object') {
return typeof value;
} else {
return Object.prototype.toString.call(value).split(' ')[1].slice(0, -1);
}
};
console.log( getType() );
console.log( getType(null) );
console.log( getType(123) );
console.log( getType('温情') );
console.log( getType({}) );
console.log( getType([]) );
console.log( getType(new Date) );