自己怎么做网站卖东西,网页传奇游戏哪个好玩,高端网站建设教程,金华网站制作推广Promise
介绍和基本使用
Promise是ES6引入的异步编程的新解决方案#xff0c;主要用来解决回调地狱问题。语法上 Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。 Promise构造函数:new Promise() Promise.prototype.then方法 Promise.prototype.ca…Promise
介绍和基本使用
Promise是ES6引入的异步编程的新解决方案主要用来解决回调地狱问题。语法上 Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。 Promise构造函数:new Promise() Promise.prototype.then方法 Promise.prototype.catch方法
//创建实例
const p new Promise(function (resolve, reject) {//模拟主体业务代码setTimeout(() {//let data 成功获取数据库中的数据;//如果获取数据成功执行resolve()函数并将返回数据作为参数传入//resolve(data);let data 获取失败;//如果获取数据失败执行reject()函数并将返回数据作为参数传入reject(data);}, 1000);
});
//调用promise实例
p.then(function (value) {//执行resolve函数执行的方法//...
}, function (reason) {//执行reject()函数执行的方法//...
});这种写法好处在于代码简洁避免了回调地狱问题。
Promise.prototype.then
调用then方法then方法的逐回结果是 Promise对象对象状态由回调函数的执行结果决定。
如果回调函数中返回的结果是非promise 类型的属性状态为成功返回值为对象的成功的值.如果回调函数中返回的结果是promise 类型的属性状态根据then方法内部Promise返回的状态决定。如果直接抛出错误返回值也是promise类型的值为抛出错误的值。
//创建实例
const p new Promise(function (resolve, reject) {//模拟主体业务代码setTimeout(() {//let data 成功获取数据库中的数据;//resolve(data);let data 获取失败;reject(data);}, 1000);
});
//调用promise实例
const result p.then(function (value) {//1非promise类型的属性return iloveyou;//2是 promise对象return new Promise((resolve, reject) {// resolve(ok);reject(error );});//3抛出错误throw new Error(出错啦!);
}, function (reason) {console.warn(reason);
});
console.log(result);由于promise返回的是promise类型所以可以进行链式调用
const fs require(fs);const p new Promise(function (resolve, reject) {fs.readFile(./source/为学.md, function (err, data) {if (err) reject(err);resolve(data);});
});p.then(value {return new Promise((resolve, reject) {fs.readFile(./source/为学1.md, function (err, data) {resolve([value, data]);});});
}).then(value {return new Promise((resolve, reject) {fs.readFile(./source/为学2.md, function (err, data) {value.push(data);return resolve(value);});});
}).then(value {console.log(value.join(\r\n));
});Promise.prototype.catch
通过cache方法可以指定Promise发生错误时的回调。
promise-ajax
const p new Promise(function (resolve, reject) {const xhr new XMLHttpRequest();xhr.open(GET, https://layuion.com/static/json/table/user.json?page1limit10);xhr.send();xhr.onreadystatechange function () {if (xhr.readyState 4) {if (xhr.status 200 xhr 400) {resolve(xhr.response);} else {reject(获取失败);}}};
});
p.then(function (value) {console.log(value);
}, function (reason) {console.log(reason);
})set
ES6提供了新的数据结构 set(集合。它类似于数组但成员的值都是唯一的(声明时即使有重复也会去重)。集合实现了Iterator接口所以可以使用扩展运算符和for ...of...进行遍历。
集合的属性和方法
size 返回集合的元素个数
add 增加一个新元素返回当前集合
delete 删除元素返回boolean值
has 检测集合中是否包含某个元素返回boolean值
//声明集合并赋值
let s1 new Set([猪, 狗, 牛, 羊, 狗]);
console.log(s1); //Set(4) {猪, 狗, 牛, 羊}
//长度
console.log(s1.size); //4
//添加
s1.add(猫);
console.log(s1); //Set(5) {猪, 狗, 牛, 羊, 猫}
//删除
s1.delete(牛);
console.log(s1); //Set(4) {猪, 狗, 羊, 猫}
//has
console.log(s1.has(猫)) //true
console.log(s1.has(鸡)) //false
//清空
s1.clear();
console.log(s1);Set(0) {size: 0}
//遍历
for (const v of s1) {console.log(v);
}集合实践
//集合实践
let a1 [1, 2, 3, 5, 5, 6, 7, 8, 6, 5];
console.log(a1); //[1, 2, 3, 5, 5, 6, 7, 8, 6, 5]
//去重
let unq [...new Set(a1)];
console.log(unq);//[1, 2, 3, 5, 6, 7, 8]
//交集
let a2 [4, 5, 6, 9, 6, 4, 3];
const result [...new Set(a1)].filter(item new Set(a2).has(item));
console.log(result); //[3, 5, 6]
//并集
console.log([...new Set([...a1, ...a2])]);
//差集- a1 和 a2取差集意思是a1里面有a2没有的数据; 也就是交集的取反
console.log([...new Set(a1)].filter(item !new Set(a2).has(item))); //[1, 2, 7, 8]map
ES6提供了Map数据结构。它类似于对象也是键值对的集合。但是“键”的范围不限于字符串各种类型的值包括对象都可以当作键。Map也实现了iterator接口所以可以使用「扩展运算符』和「 for…of…』进行遍历。
Map的属性和方法:
size 返回Map的元素个数,
set 增加一个新元素返回当前Map
get 返回键名对象的键值
has 检测Map 中是否包含某个元素返回boolean值
clear清空集合返回undefined
//声明map
let m1 new Map();
//添加
m1.set(team, IG);
m1.set(jiaolian, ssss);
m1.set(lpl, function () {console.log(IG电子竞技!);
})
let boos {boos: 王思聪
}
m1.set(boos, {上单: the shy,打野: ning,中单: rookie,adc: jacklove,辅助: baolan
});
//size
console.log(m1.size);
//删除
m1.delete(jiaolian);
//获取
console.log(m1.get(team));
console.log(m1.get(lpl));
console.log(m1.get(boos));
//清空
m1.clear();WeakMap
WeakMap 对象是一组键/值对的集合其中的键是弱引用的。其键必须是对象而值可以是任意的。它的键被弱保持也就是说当其键所指对象没有其他地方引用的时候它会被 GC 回收掉。
为什么使用weakmap?
在 JavaScript 里map API 可以 通过使其四个 API 方法共用两个数组一个存放键一个存放值来实现。给这种 map 设置值时会同时将键和值添加到这两个数组的末尾。从而使得键和值的索引在两个数组中相对应。当从该 map 取值的时候需要遍历所有的键然后使用索引从存储值的数组中检索出相应的值。
但这样的实现会有两个很大的缺点 首先赋值和搜索操作都是 O(n) 的时间复杂度n 是键值对的个数因为这两个操作都需要遍历全部整个数组来进行匹配。 简单来说就是赋值和搜索都会遍历整个数组时间复杂度都是O(n)。 另外一个缺点是可能会导致内存泄漏因为数组会一直引用着每个键和值。这种引用使得垃圾回收算法不能回收处理他们即使没有其他任何引用存在了。
相比之下WeakMap它的键被弱保持也就是说当其键所指对象没有其他地方引用的时候它会被 GC 回收掉。WeakMap提供的接口与Map相同。
与Map对象不同的是WeakMap的键是不可枚举的。不提供列出其键的方法。列表是否存在取决于垃圾回收器的状态是不可预知的。
class类
ES6提供了更接近传统语言的写法引入了Class类这个概念作为对象的模板。通过class关键字可以定义类。基本上ES6的class可以看作只是一个语法糖它的绝大部分功能ES5都可以做到新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
/*--------------------之前es5实现类的方法举例------------------------*/
//手机
function Phone(brand, price) {this.brand brand;this.price price;
}
//添加方法
Phone.prototype.call function () {console.log(我可以打电话!!);
}
//实例化对象
let Huawei new Phone(华为, 5999);
Huawei.call();
console.log(Huawei);
/*--------------------es6实现类------------------------*/
class shouji {//构造方法名字不能修改constructor(brand, price) {this.brand brand;this.price price;}call() {console.log(我可以打电话!!);}
}
let onePlus new shouji(1, 1999);
console.log(onePlus);
onePlus.call();同一作用域的类名和函数名不能相同例如上述代码的类名就不能命名为Phone。
类中构造方法不是必须要有。
静态成员
function Phone() { } //表示函数对象phone相当于面向对象里面的类。
//给函数对象添加属性它的name属性只属于Phone对象。相当于面向对象里面的静态属性
Phone.name 手机;
//给函数对象添加方法。它的change方法只属于Phone对象相当于面向对象里面的静态方法
Phone.change function () {console.log(我可以改变世界);
}
//访问函数对象属性和方法
console.log(Phone.name);
console.log(Phone.change);//可以通过函数对象的prototype属性给实例对象添加方法和属性
Phone.prototype.size 5.5inch;
let nokia new Phone(); //实例化一个对象
console.log(nokia.size); //5.5inch
//undefined 实例化对象和函数对象不相同。所以不能访问。
console.log(nokia.name);
console.log(nokia.change());//caught TypeError: nokia.change is not a functiones6中写法
class Phone{//静态属性static name 手机;//只能通过类名访问static change(){ //只能通过类名访问console.log(我可以改变世界);}
}
let nokia new Phone();
console.1og(nokia.name);
console.log(Phone.name);继承
es5里实现继承
function Phone(brand, price) {this.brand brand;this.price price;
}
Phone.prototype.call function () {console.log(我可以打电话);
}
//智能手机
function SmartPhone(brand, price, color, size) {Phone.call(this, brand, price);this.color color;this.size size;
}
//设置子级构造函数的原型
SmartPhone.prototype new Phone;
SmartPhone.prototype.constructor SmartPhone;//矫正不加也可以
//声明子类的方法
SmartPhone.prototype.photo function () {console.log(我可以拍照)
}
SmartPhone.prototype.playGame function () {console.log(我可以玩游戏);
}
const chuizi new SmartPhone(锤子, 2499, 黑色, 5.5inch );
console.log(chuizi);es6里面类的继承
class Phone {constructor(brand, price) {this.brand brand;this.price price;}call() {console.log(打电话)}
}class SmartPhone extends Phone {constructor(brand, price, color, size) {super(brand, price);this.color color;this.brand brand;}photo() {console.log(我可以拍照);}playGame() {console.log(我可以玩游戏);}
}
let xiaomi new SmartPhone(小米, 799, 粉色, 70inch);
console.log(xiaomi);es6中只允许继承一个类。
es6类中普通的方法中不允许调用super方法
重写
子类中可以声明同父类名称相同的方法。
getter和setter
getter可以对类属性绑定一个函数当调用这个属性的时候这个函数被执行这个函数的返回值就是这个属性的值。通常对对象的动态属性进行封装。
setter可以对类属性绑定一个函数当设置这个属性的时候这个函数被执行。可以对属性的合法性进行判断
class Phone {//这里的price为类Phone的属性后边的分别是getter和setter绑定的方法get price() {console.log(get price)return 90;}set price(price) {console.log(set price);}
}
let p new Phone();
console.log(p.price);//get price 90
p.price 100;//set price数值扩展
Number.EPSILON
Number.EPSILON是JavaScript表示的最小精度。
EPSILON属性的值接近于2.2204460492503130808472633361816E-16。
通常用于两个数字进行比较如果结果比Number.EPSILON小或等于这个数就认为这两个数字相等。
function equal(a, b) {if (Math.abs(a - b) Number.EPSILON) {return true;} else {return false;}
}
console.log(0.1 0.2 0.3); //false
console.log(equal(0.1 0.2, 0.3)) //true二进制和八进制
let b 0b1010; //二进制
let o 0o777; //八进制
let d 100; //十进制
let x 0xff; //16进制Number.isFinite()
检测一个数值是否为有限数
console.log(Number.isFinite(100)); //true
console.log(Number.isFinite(100/0)); //false
console.log(Number.isFinite(Infinity));//falseNumber.isNaN()
Number.isNaN()检测一个数值是否为NaN
Number.parseInt() Number.parseFloat()
字符串转整数
Number.isInteger()
判断一个数是否为整数
Math.trunc()
将数字的小数部分抹掉
Math.sign()
判断一个数到底为正数、负数还是零
对象的方法扩展
object.is()
判断两个值是否完全相等。和略有不同判断NaN的时候不一样。
console.log(Object.is(120,120));//true
console.log(Object.is(NaN,NaN));//true
console.log(NaN NaN);//falseObject.assign()
对象的合并。如果合并的对象中有相同的属性或方法后边的会覆盖前边的属性或方法。
get或set原型对象
Object.setPrototype0f 设置原型对象
Object.getPrototypeof 获取原型对象
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的好处
防止命名冲突
代码复用
高维护性
模块化规范产品
ES6 之前的模块化规范有:
CommonJs规范 NodeJS、Browserify产品
AMD规范 requireJs产品
CMD规范 seaJs产品
ES6模块化语法
模块功能主要由两个命令构成: export和 import。
export命令用于规定模块的对外暴露接口。
/*---./js/m1.js---*/
//分别暴露
export let s 测试模块;
export function change() {console.log(用心改变世界);
}上边的使用export分别将s和change暴露。还有以下两种暴露方式 统一暴露在最底部写入一下代码export {s, change}; 默认暴露default里面可以跟任意数据对象居多。这种方式使用的时候就要多加个default例如m1.default.school //默认暴露
export default {s: 测试模块,change: function(){console.log(我们可以改变你!!);}
}import命令用于输入其他模块提供的功能
import * as m1 from ./js/m1.js;
console.log(m1);上边的代码使用的是通用导入方式还有以下两种导入方式 解构赋值形式 import {s, change} from ./js/m1.js;
import {s as guigu, change} from ./js/m2.js; //与第一个s重名可以使用as命名别名
import {default as m3} from ./js/m3.js;简便形式只能针对默认暴路 import m3 from ./js/m3.js;
console.log(m3);一般引入模块都是放在一个入口文件里面如:app.js, 在html中使用时候引入这个文件就可以了
script src./src/js/app.js typemodule/script 注意typemodule.
在js文件中只要使用了import语句不管import之间是否有javascript语句都会按import顺序先执行import的语句
es6模块化代码转换
由于es6语法对所有的浏览器都都不一定支持所以考虑到兼容性需要将es6模块代码转换成es5代码。 安装工具 babel-cli(babel客户端命令行) babel-preset-env(babel环境) browserify(项目中一般使用webpack打包) 使用命令npx babel src/js -d dist/js --presetsbabel-preset-env如果全局安装babel,可以直接使用babel命令babel src/js -d dist/js --presetsbabel-preset-env. 命令的格式 [npx] babel 要转换文件路径 -d 转换完成后要存储的文件路径 --presetsbabel-preset-env 打包npx browserify dist/js/app.js -o dist/bundle.js。
打包完成后就可以在html引入了。每次更改都需要进行上述2、3步操作。
proxy
Proxy 对象用于创建一个对象的代理从而实现基本操作的拦截和自定义如属性查找、赋值、枚举、函数调用等。proxy 是javascript的内置对象在es6中被引入。
语法
const p new Proxy(target, handler)参数
target : 要使用 Proxy 包装的目标对象引用类型:对象数组函数map, set, 甚至另一个代理。
handler : 一个通常以函数作为属性的对象各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
let person {name: John,age: 21,
};const p new Proxy(person, {/*** 拦截读取属性* param target 目标对象* param property 被获取的属性名。* param receiver Proxy 或者继承 Proxy 的对象*/get(target, property, receiver) {},/*** 拦截赋值属性* param target 目标对象* param property 被设置的属性名。* param value 属性值* param receiver Proxy 或者继承 Proxy 的对象* returns boolean*/set(target, property, value, receiver) {return true;},/*** 拦截方法调用* param target 目标对象函数* param thisArg 被调用时的上下文对象* param argumentsList 被调用时的参数数组。* apply方法可以返回任何值。*/apply(target, thisArg, argumentsList) {},/*** 用于拦截 new 操作符* param target 目标对象* param argumentsList constructor 的参数列表* param newTarget 最初被调用的构造函数* construct 方法必须返回一个对象。*/construct(target, argumentsList, newTarget) {return {};},/*** 用于拦截 in 操作符* param target 目标对象。* param prop 需要检查是否存在的属性。* has 方法返回一个 boolean 属性的值。*/has(target, prop) {return true;},/*** 法用于拦截 Reflect.ownKeys()* param target 目标对象*/ownKeys(target) {return Reflect.ownKeys(target);},/*** 用于拦截对对象属性的 delete 操作。* param target 目标对象。* param property 待删除的属性名。* returns boolean*/deleteProperty(target, property) {return true;},
});Reflect
Reflect 是一个内置的对象它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US) 的方法相同。Reflect 不是一个函数对象因此它是不可构造的。反射就是将代理的内容反射出去。
与大多数全局对象不同 Reflect 并非一个构造函数所以不能通过 new 运算符对其进行调用或者将 Reflect 对象作为一个函数来调用。Reflect 的所有属性和方法都是静态的。
注意Reflect的静态方法是直接使用的
const p new Proxy(person, {/*** 拦截读取属性* param target 目标对象* param property 被获取的属性名。* param receiver Proxy 或者继承 Proxy 的对象*/get(target, property, receiver) {if (target.age 15) {return Reflect.get(target, property, receiver); //直接使用和对象操作一样} else {return John成年了!!!;}},静态方法
Reflect.apply(target, thisArgument, argumentsList)
对一个函数进行调用操作同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。Reflect.construct(target, argumentsList[, newTarget])
对构造函数进行 new 操作相当于执行 new target(...args)。Reflect.deleteProperty(target, propertyKey)
作为函数的delete操作符相当于执行 delete target[name]。Reflect.get(target, propertyKey[, receiver])
receiver可以理解为上下文this对象
获取对象身上某个属性的值类似于 target[name]。Reflect.getPrototypeOf(target)
类似于 Object.getPrototypeOf()。Reflect.has(target, propertyKey)
判断一个对象是否存在某个属性和 in 运算符 的功能完全相同。Reflect.isExtensible(target)
类似于 Object.isExtensible().Reflect.ownKeys(target)
返回一个包含所有自身属性不包含继承属性的数组。(类似于 Object.keys(), 但不会受enumerable 影响).Reflect.preventExtensions(target)
类似于 Object.preventExtensions()。返回一个Boolean。Reflect.set(target, propertyKey, value[, receiver])
将值分配给属性的函数。返回一个Boolean如果更新成功则返回true。在面向对象中反射的三种用法1、查看元数据。2、动态创建对象。3、动态调用方法。
示例
模拟mobx
const list: SetFunction new Set();
const autorun (cb: Function) {list.add(cb);
};
const observable T extends object(target) {return new Proxy(target, {set(target, p, newValue, receiver) {const result Reflect.set(target, p, newValue, receiver);list.forEach((fn) fn());return result;},});
};
const dog observable({ name: 阿黄, age: 1 });
autorun(() {console.log(change);
});dog.name 阿绿; //change
dog.age 2; //change