1.什么是异步,非IO操作的异步和IO操作的异步?
js的异步简单的说就是2段代码,代码段1先加载,但是并没有执行,代码段2却在代码段1之前执行得到了结果.js的异步是怎么实现的呢?按说代码的都是按先后顺序加载到内存并执行的,但js是利用事件的循环机制来达到异步的.上面提到的代码段1没有执行去哪了呢?其实在node(js)启动的时候就会创建一个事件循环的循环队列.循环队列里的执行细节(也会有先后顺序跟线程和事件的类型有关)就不说了,每次调用循环队列的时候就会取出循环队列里面正在等待处理的函数(这些函数都会按时间顺序排好队,如果上一个事件太浪费时间就会造成后面的定时器事件的超时了),然后执行.反复询问事件队列里,还有没有回调函数要执行,没有的话,退出当前线程. 非IO操作的异步就是js提供的定时器方法.setTimeOut(),setInterval(),setImmediate()以及process.nextTik()IO操作的异步一般都是我们调用后台接口或者读取文件流.一般会使用promise来把异步变为同步执行,对异步的结果进一步操作.
附录:
(在网上找的这几个定时器的区别,process.nextTick()这个好像只有node有js没有) 都是在主线程结束后执行,但是执行的顺序有可能不同,setTimeout采用的是类似IO观察者,setImmediate采用的是check观察者,而process.nextTick()采用的是idle观察者。
三种观察者的优先级顺序是:idle观察者>>io观察者>check观察者
process.nextTick(),效率最高,消费资源小,但会阻塞CPU的后续调用;
setTimeout(),精确度不高,可能有延迟执行的情况发生,且因为动用了红黑树,所以消耗资源大;
setImmediate(),消耗的资源小,也不会造成阻塞,但效率也是最低的。
2.import 和 export
import * as example from "./example.js"
有一种特殊情况,即允许你将整个模块当作单一对象进行导入
该模块的所有导出都会作为example对象的属性访问
1.用export default people导出时,就用 import people 导入(不带大括号)
2.一个文件里,有且只能有一个export default,但可以有多个export(默认导入的不需要带大括号,其他的
访问都需要带)。
3.当用export name 时,就用import { name }导入(记得带上大括号)
3.巧用typeof()
es6开始以后变量的声明可以是块级作用域(可以杜绝变量提升),就会有时候不小心在声明变量之前使用了
该变量,就会造成程序报错,这个时候可以使用typeof这个函数做判断,如果不存在就在声明一下,因为typeof
在判断不存在的变量的时候会返回undefined.
4.let和const
在全局作用于中,即使使用了let去声明变量,也不会污染全局系统默认的变量,但是var就会干掉全局同名的变量
5.对象属性的访问
.和[]的一个区别,在es6中允许使用任意字符串做对象的key,但是同时带来了一个问题就是,这个key中有可能
出现空格,这样的值如果要访问属性就需要使用[]的样式访问,点操作符就不能访问,会抛出错误.
6.对象的原型
es6中允许指定实例继承的对象原型方法:Object.setPrototypeof()
super可以操作原型上的属性和方法(特别是重名的)
7.Set
Set对象可以用来数组去重,不允许有重复的值,不进行数据的强制类型的转换
8.webpack里的axios跨域问题
proxyTable: {
'/part/api':{
target: 'http://192.168.1.0:9000',
changeOrigin: true, //是否跨域
pathRewrite: {
'/part/api':'/api'
}
}
};
9.自定义类中方法名
let methodName = "sayName";
class PersonClass {
constructor(name) {
this.name = name;
}
[methodName]() {
console.log(this.name);
}
}
let me = new PersonClass("Nicholas");
me.sayName();
10.对象的合并
对象的浅合并
Object.assign({},{
a:1
},{
a:2
})
对象深层次的合并解决方案
Object.assign({},{
a:{
c:1,
s:2
}
},{
a:Object.assign({},{
c:1,
s:2
},{
c:2
})
})
11.类的继承原理
let obj = {}
Object.create(obj)
12.类的继承(调用父类中的方法)
class Person {
constructor(name,age){
this.name = name,
this.age = age
}
say () {
console.log(this.name+'会说话')
}
}
class Student extends Person {
constructor(name){
super(name)
super.say()
}
}
let jiang = new Student('jianglu',20);
jiang.say();
//输出结果:
// jianglu会说话
// jianglu会说话
13.Object构造函数的方法
Object.assign()
//通过复制一个或多个对象来创建一个新的对象。
Object.create()
//使用指定的原型对象和属性创建一个新对象。
Object.defineProperty()
//给对象添加一个属性并指定该属性的配置。
Object.defineProperties()
//给对象添加多个属性并分别指定它们的配置。
Object.entries()
//返回给定对象自身可枚举属性的[key, value]数组。
Object.freeze()
//冻结对象:其他代码不能删除或更改任何属性。
Object.getOwnPropertyDescriptor()
//返回对象指定的属性配置。
Object.getOwnPropertyNames()
//返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名。
Object.getOwnPropertySymbols()
//返回一个数组,它包含了指定对象自身所有的符号属性。
Object.getPrototypeOf()
//返回指定对象的原型对象。
Object.is()
//比较两个值是否相同。所有 NaN 值都相等(这与==和===不同)。
Object.isExtensible()
//判断对象是否可扩展。
Object.isFrozen()
//判断对象是否已经冻结。
Object.isSealed()
//判断对象是否已经密封。
Object.keys()
//返回一个包含所有给定对象自身可枚举属性名称的数组。
Object.preventExtensions()
//防止对象的任何扩展。
Object.seal()
//防止其他代码删除对象的属性。
Object.setPrototypeOf()
//设置对象的原型(即内部[[Prototype]]属性)。
Object.values()
//返回给定对象自身可枚举值的数组。
14.NaN问题
console.log(Object.is(NaN,NaN)) //true console.log(NaN == NaN) //false
console.log(typeof NaN)//number
15.判断数组是否相等
if(Array.prototype.equals)
Array.prototype.equals = function (array) {
if (!array)
return false;
if (this.length != array.length)
return false;
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] instanceof Array && array[i] instanceof Array) {
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] !== array[i]) {
return false;
}
}
return true;
}
Object.defineProperty(Array.prototype, "equals", {enumerable: false});
16.模仿类的私有方法
let aa = Symbol('hello');
class P {
//创建私有方法
[aa](){
console.log('私有方法');
}
//公共方法
add(){
this[aa]();
}
}
let person = new P();
person.add();
person[aa]();
17.类的语法糖
/**
* 类的模拟
*/
function Person(name,age){
this.name = name;
this.age = age;
this.say = function(){
console.log(`我的名字是${name},年龄是${age}`);
}
}
let jiang = new Person('jiang lu', 20);
jiang.say();
function Ren1(name,age){
Person.call(this,name,age);
}
let jiang1 = new Ren1('tong xue',30);
jiang1.say();
/**
* ES6 类的语法糖
*/
class Person1{
constructor(name,age){
this.name = name;
this.age = age;
}
say(){
console.log(`我的名字是${this.name},年龄是${this.age}`);
}
}
let tong = new Person1('jiang lu', 20);
tong.say();
// 继承
class Ren extends Person1{
constructor(name,age){
super();
this.name = name;
this.age = age;
}
}
let tong1 = new Ren('tong xue', 18);
tong1.say();