做用域就是变量的做用范围。也就是你声明一个变量之后,这个变量能够在什么场合下使用。之前的JavaScript只有全局做用域,和函数做用域。javascript
1.var 没有块级做用域,定义后在当前包中都均可以访问,若是变量名重复,就会覆盖前面定义的变量,而且很能够被他人修改。css
if(true){
var a = "a"; //指望a是某一个值
}
console.log(a);
复制代码
2.var 在for循环标记变量共享,通常在循环中会使用的i会被共享,其本质也是因为没有块级做用域形成的
html
for (var i = 0; i < 3; i++) {
setTimeout(function () {
alert(i);
}, 0);
}
// 结果就是 弹窗三次 3
for ( i = 0; i < 3; i++) {
setTimeout(function () {
alert(i);
}, 0);
}
// 结果就是 弹窗三次 0-2
复制代码
在用var定义变量的时候,变量经过闭包进行隔离的,如今用了let,不只仅能够经过闭包隔离,还能够增长了一些块级做用域隔离。块级做用用一组大括号定义一个快,使用let定义的变量字啊大括号的外面是访问不到的。java
if(ture){
let name = 'wjh'
}
consloe.log('name'); // ReferenceError: name is not defined
复制代码
if(ture){
let name = 'wjh'
}
console.log(window.name); // undefined
复制代码
// 嵌套循环不会相互影响
for (let i = 0; i < 3; i++) {
console.log("out", i);
for (let i = 0; i < 2; i++) {
console.log("in", i);
}
}
// 结果 out 0 in 0 in 1 out 1 in 0 in 1 out 2 in 0 in 1
复制代码
if(ture){
let a = 1;
let a = 2; //Identifier 'a'
}
复制代码
for(let i = 0;i<2;i++){
console.log('inner',i);
let i =100;
}
// 结果 i is not defined
复制代码
;(function(){
})();
复制代码
如今git
{
}
复制代码
使用 const 咱们能够声明一个常量,一旦声明以后,就不能够更改。github
const MY_NAME = 'wjw';
MY_NAME = 'wjw2';//Assignment to constant variable
复制代码
注意const限制的是不能给变量从新赋值,而变量的值自己是能够改变的,下面的操做是能够的ajax
const names = ['wjw1'];
names.push('wjw2');
console.log(names);
复制代码
const A = "0";
{
const A = "A";
console.log(A)
}
{
const A = "B";
console.log(A)
}
console.log(A)
// 结果 A B 0
复制代码
解构意思就是分解一个东西的结构,能够用一种相似数组的方式定义N个变量,能够将一个数组中的值按照规则赋值过去。
npm
var [name,age]=['wjh',8];
console.log(name,age);
复制代码
let [x,[y],z]=[1,[2.1]];
console.log(x,y,z);
let [x,[y,z]] = [1,[2.1,2.2]];
console.log(x,y,z);
let [json,arr,num] = [{name:'wjw'},[1,2],3];
console.log(json,arr,num);
// 1 2.1 undefined 1 2.1 2.2 { name: 'wjw' } [ 1, 2 ] 3
复制代码
let [,,x]=[1,2,3]
console.log(x);
复制代码
对象也能够被解构json
var obj = {name:'wjw',age:8};
//对象里的name属性的值会交给name这个变量,age的值会交给age这个变量
var {name,age} = obj
//对象里的name属性的值会交给myname这个变量,age的值会交给myage这个变量
let {name: myname, age: myage} = obj;
console.log(name,age,myname,myage);
复制代码
在赋值和传参的时候可使用默认值bootstrap
let [a='a',b='b',c=new Error('C必须指定')] = [1, , 3];
console.log(a,b,c);
function ajax(options){
var method = options.method || "get";
var data = options.data || {};
}
function ajax(method='get',data){
console.log(arguments);
}
ajax({
method:'post',
data:{'name':'wjh'}
})
复制代码
模板字符串用反应号(数字1左边的那个建)包含,用${}
括起来
var name = 'wjw',age = 8;
let desc = `${name} is ${age} old!`;
console.log(desc);
//全部模板字符串的空格和换行,都是被保留的
var str = `<ul> <li>a</li> <li>b</li> </ul>`;
console.log(str);
复制代码
其中的变量会用变量的值替换掉
function replace(desc){
return desc.replace(/\$\{([^}]+)\}/g,function(matched,key){
return eval(key);
});
}
复制代码
能够在模板字符串的前面添加一个标签,这个标签能够去处理模板字符串 标签其实就是一个函数,函数能够接收两个参数,一个是 strings 就是模板字符串里的每一个部分的字符 还有一个参数可使用rest的形式values,这个参数里面是模板字符串里的值。
var name = 'wjh',age = 8;
function desc(strings,...values){
console.log(strings,values);
}
desc`${name} is ${age} old!`;
复制代码
字符串新方法
var s = 'wjh';
s.startsWith('w') // true
s.endsWith('h') // true
s.includes('j') // true
复制代码
第二个参数,表示开始搜索的位置
var s = 'wjh';
console.log(s.startsWith('j',2)); // true
console.log(s.endsWith('j',2)); // true
console.log(s.includes('j',2)); // false
复制代码
endsWith的行为与其余其余方法有所不一样。它针对前n个字符,而其余方法是从第几位开始到字符串结束
repeat 方法返回一个新字符串,表示将原字符串重复n次。
'x'.repeat(3);
'x'.repeat(0);
复制代码
能够给定义的函数接收的参数设置默认的值 在执行这个函数的时候,若是不指定函数的参数的值,就会使用参数的这些默认的值。
function ajax(url,method='GET',dataType="json"){
console.log(url);
console.log(method);
console.log(dataType);
}
复制代码
把...放在数组前面能够把一个数组进行展开,能够把一个函数而不须要使用apply
//传入参数
let print = function(a,b,c){
console.log(a,b,c);
}
print([1,2,3]);
print(...[1,2,3]);
// 能够替代apply
var m1 = Math.max.apply(null, [8, 9, 4, 1]);
var m2 = Math.max(...[8, 9, 4, 1]);
// 能够替代concat
var arr1 = [1, 3];
var arr2 = [3, 5];
var arr3 = arr1.concat(arr2);
var arr4 = [...arr1, ...arr2];
console.log(arr3,arr4);
//类数组的转数组
function max(a,b,c) {
console.log(Math.max(...arguments));
}
max(1, 3, 4);
复制代码
剩余操做符能够把其他参数的值放在一个叫作b的数组里
let rest = function(a,...rest){
console.log(a,rest);
}
rest(1,2,3);
复制代码
let destruct = function({name,age}){
console.log(name,age);
}
destruct({name:'wjh',age:10})
复制代码
箭头函数简化了函数的定义方式
[1,2,3].forEach(val=>console.log(val));
复制代码
输入参数若是多于一个要用()包含,函数体若是有多条语句须要用{}包起来
箭头函数根本没有本身的this,致使内部的this就是外层代码块的this。 正是由于它没有this,从而避免了this指向的问题。
var person = {
name:'wjh',
getName:function(){
- setTimeout(function(){console.log(this);},1000); //在浏览器执行的话this指向window
+ setTimeout(() => console.log(this),1000);//在浏览器执行的话this指向person
}
}
person.getName();
复制代码
// 相同的阵列
var people = [
{
name : 'Casper' ,
like : '锅烧意面' ,
age : 18
},
{
name : 'Wang' ,
like : '炒面' ,
age : 24
},
{
name : 'Bobo' ,
like : '萝卜泥' ,
age : 1
},
{
name : '卤蛋' ,
like : '萝卜泥' ,
age : 3
}
];
复制代码
filter() 会回传一个阵列,其条件是return 后方为true 的物件,很适合用在搜寻符合条件的资料。
var filterEmpty = people.filter( function ( item, index, array ) {
});
console.log(filterEmpty); //没有条件,会是一个空阵列
var filterAgeThan5 = people.filter( function ( item, index, array ) {
return item.age > 5 ; //取得大于五岁的 若是这边符合条件 只要为ture便可
});
console .log(filterAgeThan5); // Casper, Wang这两个物件
复制代码
find()与filter()很像,但find() 只会回传一次值,且是第一次为true的值。
var findEmpty = people.find( function ( item, index, array ) {
});
console .log(findEmpty); //没有条件,会是undefined
var findAgeThan5 = people.find( function ( item, index, array ) {
return item.age > 5 ; //取得大于五岁的
});
console .log(findAgeThan5); //虽然答案有两个,但只会回传Casper这一个物件
var findLike = people.find( function ( item, index, array ) {
return item.like === '萝卜泥' ; //取得阵列like === '萝卜泥'
});
console .log(findLike); //虽然答案有两个,但只会回传第一个Bobo物件
复制代码
forEach 是这几个阵列函式最单纯的一个,不会额外回传值,只单纯执行每一个阵列内的物件或值。
var forEachIt = people.forEach( function ( item, index, array ) {
console .log(item, index, array); //物件,索引,所有阵列
return item; // forEach没在return的,因此这边写了也没用
});
console .log(forEachIt); // undefined
people.forEach( function ( item, index, array ) {
item.age = item.age + 1 ; // forEach就如同for,不过写法更容易
});
console .log(people); //所有age + 1
复制代码
使用map() 时他须要回传一个值,他会透过函式内所回传的值组合成一个阵列。 若是不回传则是 undefined 回传数量等于原始阵列的长度 这很适合将原始的变数运算后从新组合一个新的阵列。
var mapEmpty = people.map( function ( item, index, array ) {
});
console .log(mapEmpty); // [undefined, undefined, undefined, undefined]
var mapAgeThan5 = people.map( function ( item, index, array ) {
return item.age > 5 ; //比较大于五岁的
});
console .log(mapAgeThan5); // [true, true, false, false]
var mapAgeThan5_2 = people.map( function ( item, index, array ) {
// 错误示范
if (item.age > 5 ) {
return item; //回传大于五岁的
}
return false ; //别觉得空的或是false就不会回传
});
console .log(mapAgeThan5_2); // [{name: 'Casper'...}, {name: 'Wang'...}, false, false]
var mapEat = people.map( function ( item, index, array ) {
if (item.like !== '萝卜泥' ) {
return ` ${item.like}好吃` ;
} else {
return ` ${item.like}很差吃` ;
}
});
console .log(mapEat); // ["锅烧意面好吃", "炒面好吃", "萝卜泥很差吃", "萝卜泥很差吃"]
复制代码
every()能够检查全部的阵列是否符合条件,这仅会回传一个值trueor false,能够用来检查阵列中的内容是否符合特定条件。
var ans = array.every( function ( item, index, array ) {
console .log(item, index, array); //物件,索引,所有阵列
return item.age > 10 //当所有age大于10才能回传true
});
console .log(ans); // false:只要有部分不符合,则为false
var ans2 = array.every( function ( item, index, array ) {
return item.age < 25
});
console .log(ans2); // true:所有age都小于25
复制代码
some() 与every() 很是接近,都是回传true or false,差别仅在every() 需彻底符合,some() 仅须要部分符合。
var ans = people.some( function ( item, index, array ) {
return item.age > 10 //当所有age大于10才能回传true
});
console .log(ans); // true:只要有部分符合,则为true
var ans2 = people.some( function ( item, index, array ) {
return item.age < 25
});
console .log(ans2); // true:只要有部分符合,则为true
var ans2 = people.some( function ( item, index, array ) {
return item.age > 25
});
console .log(ans2); // false:所有都不符合则为false
复制代码
reduce() 和其余几个差别就很大了,他能够与前一个回传的值再次做运算,参数包含如下: accumulator: 前一个参数,若是是第一个阵列的话,值是以另外传入或初始化的值 currentValue: 当前变数 currentIndex: 当前索引 array: 所有阵列
var reduceEmpty = people.reduce( function ( accumulator, currentValue, currentIndex, array ) {
});
console .log(reduceEmpty); //没有条件,会是undefined
var reducePlus = people.reduce( function ( accumulator, currentValue, currentIndex, array ) {
// 分别为前一个回传值, 目前值, 当前索引值
console .log(accumulator, currentValue, currentIndex);
return accumulator + currentValue.age; //与前一个值相加
}, 0 ); //传入初始化值为0
console .log(reducePlus); //总和为46
var reducePlus = people.reduce( function ( accumulator, currentValue, currentIndex, array ) {
console .log( 'reduce' , accumulator, currentValue, currentIndex)
return Math .max( accumulator, currentValue.age ); //与前一个值比较哪一个大
}, 0 );
console .log(reducePlus); //最大值为24
复制代码
若是你想在对象里添加跟变量名同样的属性,而且属性的值就是变量表示的值就能够直接在对象里加上这些属性
let name = 'wjh';
let age = 8;
let getName = function(){
console.log(this.name)
}
let person ={
name,
age,
getName
}
person.getName();
复制代码
对比两个值是否相等
console.log(Object.is(NaN,NaN));
复制代码
把多个对象的属性复制到一个对象中,第一个参数是复制的对象,从第二个参数开始日后,都是复制的源对象
var nameObj = {name:'wjh'}
var ageObj = {age:8};
var obj = {};
Object.assign(obj,nameObj,ageObj);
console.log(obj);
//克隆对象
function clone(obj){
return Object.assgin({},obj);
}
复制代码
将一个指定的对象原型设置为另外一个对象或者null
var obj1 = {name:'wjh1'};
var obj2 = {name:'wjh2'};
var obj = {};
Object.setPrototypeOf(obj,obj1);
console.log(obj.name);
console.log(Object.getPrototypeOf(obj));
Object.setProtoypeOF(obj,obj2);
console.log(obj.name);
console.log(Object.getPrototypeOf(obj));
复制代码
直接对象表达式中设置prototype
var obj1 = {name:'wjh'};
var obj3 = {
_proto_:obj1
}
console.log(obj3.name);
console.log(Object.getPrototypeOf(obj3));
复制代码
经过super能够调用protype上的属性或方法
let person ={
eat(){
return 'milk';
}
}
let student = {
_proto_:person,
eat(){
return super.eat()+'bead'
}
}
console.log(student.eat());
复制代码
使用 class 这个关键词定义一个类,基于这个建立实例之后就会建立 constructor 方法,此方法能够用来初始化
class Person{
constructor(name){
this.name = name;
}
getName(){
console.log(this.name)
}
}
let person = new Person('wjh');
person.getName();
复制代码
getter 能够用来获取属性,setter 能够去设置属性
class Person {
constructor(){
this.hobbies = [];
}
set hobby(hobby){
this.hobbies.push(hobby);
}
get hobby(){
return this.hobbies;
}
}
let person = new Person();
person.hobby = 'aa';
person.hobby = 'bb';
console.log(person.hobby)
复制代码
在类里面添加静态的方法可使用static 这个关键词,静态方法就是不须要实例化类就能使用的方法
class Person{
static add(a,b){
return a+b;
}
}
console.log(Person.add(1,x));
复制代码
一个类能够继承其余的类里的东西
class Person{
constructor(name){
this.name = name;
}
}
class Teacher extends Person{
constructor(name,age){
super(name);
this.age = age;
}
}
var teacher = Teacher('wjh',8);
console.log(teacher.name,teacher.age)
复制代码
Generator 是一个特殊的函数,执行它会返回一个Iterator对象。经过遍历迭代器,Generator函数运行后悔返回遍历器对象,而不是函数的返回值。
迭代器有一个next方法,每次执行的时候会返回一个对象 对象里面有两个函数,一个是value表示返回的值,还有就是布尔值done,表示是迭代完成
function buy(books){
let i = 0;
return{
next(){
let done = i ===books.length;
let value = !done ? books[i++]:undefined;
return {
value:value,
done:done
}
}
}
}
let iterators = buy(['js','html']);
var curr;
do{
curr = iterators.next();
console.log(curr);
}while(!curr.done);
复制代码
生成器用于建立迭代器
function* buy(boos){
for(var i=0;i<boos.length;i++){
yield books[i];
}
}
let buying = buy(['js','html]);
var curr;
do {
curr = buying.next();
console.log(curr);
}while(!curr.done);
复制代码
一个Set是一堆东西的集合,Set 有点像数组,不过跟数组不同的是,Set里面不能有重复的内容
var books = new Set();
books.add('js');
books.add('js');//添加剧复元素的集合元素个数不会变化
books.add('html');
books.forEach(function(book){ // 循环集合
console.log(book);
})
console.log(book.size);//集合中元数的个数
console.log(books.has('js'));//判断集合是否有此元素
books.delete('js');
console.log(books.size);
console.log(books.has('js'));
books.clear();//清空set
console.log(books.size);
复制代码
可使用Map来组织这个名值对的数据
var books = new Map();
books.set('js',{name:'js'});//向map中添加元素
books.set('html',{name:'html'});
console.log(books.size);//查看集合中的元素
console.log(books.get('js'));//经过key获取值
books.delete('js');//执行key删除元素
console.log(books.has('js'));//判断map中有没有key
book.forEach((value,key)=>{
console.log(key+'='+value);
})
books.clear();//清空map
复制代码
能够根据应用的需求吧代码分红不一样的模块,每一个模块里能够导出它须要让其余模块使用的东西,在其余模块里面能够导入这些模块,导出的东西。
在浏览器中使用模块须要借助 导出
export var name = 'wjh';
export var age = 8;
复制代码
导入
//import {name,age} from './school.js';
import * as school from './school.js';
console.log(school.name,school.age);
复制代码
在页面中引用
<script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
<script src="https://google.github.io/traceur-compiler/bin/BrowserSystem.js"></script>
<script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>
<script type="module" src="index.js"></script>
复制代码
导出时重命名
function say(){
console.log('say');
}
export {say as say2};
复制代码
导入时重命名
import {say2 as say3} from './school.js'
复制代码
每一个模块均可以有一个默认要导出的东西
export default function say(){
console.log('say')
}
复制代码
导入
import say from './school.js'
复制代码
var parent = {
age: 5,
hobby: [1, 2, 3],
home: {city: '北京'},
};
var child = extendDeep(parent);
child.age = 6;
child.hobby.push('4');
child.home.city = '广东';
console.log('child ', child); //[1, 2, 3, 4]
console.log('parent ', parent);
function extend(parent) {
let child;
if (Object.prototype.toString.call(parent) == '[object Object]') {
child = {};
for (let key in parent) {
child[key] = extend(parent[key])
}
} else if (Object.prototype.toString.call(parent) == '[object Array]') {
child = parent.map(item => extend(item));
} else {
return parent;
}
return child;
}
function extendDeep(parent, child) {
child = child || {};
for (var key in parent) {
if (typeof parent[key] === "object") {
child[key] = (Object.prototype.toString.call(parent[key]) === "[object Array]") ? [] : {};
extendDeep(parent[key], child[key]);
} else {
child[key] = parent[key];
}
}
return child;
}
复制代码
function test(fruit) {
if (fruit == 'apple' || fruit == 'strawberry') {
console.log('red');
}
}
复制代码
优化变成 ->>
function test(fruit) {
// 条件提取到数组中
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (redFruits.includes(fruit)) {
console.log('red');
}
}
复制代码
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1:fruit 必须有值
if (fruit) {
// 条件 2:必须为红色
if (redFruits.includes(fruit)) {
console.log('red');
// 条件 3:数量必须大于 10
if (quantity > 10) {
console.log('big quantity');
}
}
} else {
throw new Error('No fruit!');
}
}
// 测试结果
test(null); // 抛出错误:No fruits
test('apple'); // 打印:red
test('apple', 20); // 打印:red,big quantity
复制代码
优化
/* 在发现无效条件时提早 return */
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1:提早抛出错误
if (!fruit) throw new Error('No fruit!');
// 条件2:必须为红色
if (redFruits.includes(fruit)) {
console.log('red');
// 条件 3:数量必须大于 10
if (quantity > 10) {
console.log('big quantity');
}
}
}
复制代码
为了减小一个嵌套层级,优化编码风格
/* 在发现无效条件时提早 return */
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (!fruit) throw new Error('No fruit!'); // 条件 1:提早抛出错误
if (!redFruits.includes(fruit)) return; // 条件 2:当 fruit 不是红色的时候,提早 return
console.log('red');
// 条件 3:必须是大量存在
if (quantity > 10) {
console.log('big quantity');
}
}
复制代码
function test(fruit, quantity) {
if (!fruit) return;
const q = quantity || 1; // 若是没有提供 quantity 参数,则默认为 1
console.log(`We have ${q} ${fruit}!`);
}
// 测试结果
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
复制代码
可是q在这边不直观全部优化
function test(fruit, quantity = 1) { // i若是没有提供 quantity 参数,则默认为 1
if (!fruit) return;
console.log(`We have ${quantity} ${fruit}!`);
}
// 测试结果
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
复制代码
可是这边 也多是个对象
// 解构 —— 只得到 name 属性
// 参数默认分配空对象 {}
function test({name} = {}) {
console.log (name || 'unknown');
}
//测试结果
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
复制代码
function test(color) {
// 使用 switch case 语句,根据颜色找出对应的水果
switch (color) {
case 'red':
return ['apple', 'strawberry'];
case 'yellow':
return ['banana', 'pineapple'];
case 'purple':
return ['grape', 'plum'];
default:
return [];
}
}
//测试结果
test(null); // []
test('yellow'); // ['banana', 'pineapple']
复制代码
这边建议使用对象,更加清晰
// 使用对象字面量,根据颜色找出对应的水果
const fruitColor = {
red: ['apple', 'strawberry'],
yellow: ['banana', 'pineapple'],
purple: ['grape', 'plum']
};
function test(color) {
return fruitColor[color] || [];
}
复制代码
可是这边是颇有可能为网络数据,没法判断red这样的变量,那么就用arry.filter 来过滤
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'strawberry', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'pineapple', color: 'yellow' },
{ name: 'grape', color: 'purple' },
{ name: 'plum', color: 'purple' }
];
function test(color) {
// 使用 Array filter ,根据颜色找出对应的水果
return fruits.filter(f => f.color == color);
}
复制代码
咱们想检查全部水果是否都是红色的
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
let isAllRed = true;
// 条件:全部的水果都必须是红色
for (let f of fruits) {
if (!isAllRed) break;
isAllRed = (f.color == 'red');
}
console.log(isAllRed); // false
}
复制代码
使用 arry.every来过滤
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
// 条件:简短方式,全部的水果都必须是红色
const isAllRed = fruits.every(f => f.color == 'red');
console.log(isAllRed); // false
}
复制代码
若是咱们想要检查是否有至少一个水果是红色的,咱们可使用 Array.some 仅用一行代码就实现出来
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
// 条件:是否存在红色的水果
const isAnyRed = fruits.some(f => f.color == 'red');
console.log(isAnyRed); // true
}
复制代码
在须要多个操做的时间,会致使多个回调函数嵌套,致使代码不够直观,就常说的回调地狱
若是几个异步操做之间并无先后顺序之分,但须要等多个异步完成操做完成后才能执行后续的任务,没法实现并行节约时间
promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。什么时间会用到过一段时间?答案是异步操做,异步是指可能比较长时间才有结果的才作,例如网络请求、读取本地文件等
then方法就是用来指定Promise 对象的状态改变时肯定执行的操做,resolve时执行第一个函数(onFulfilled),reject时执行第二函数(onRejected)
let promise = new Promise((resolve,reject)=>{
setTimeout(()=>{
if(Math.random()>0.5)
resolve('This is resolve!')
else
reject('This is reject')
},1000);
});
promise.then(Fulfilled,Rejected)
复制代码
function Promise(fn){
this.success(data);
},(error)=>{
this.error();
}
Promise.prtotype.resolve = function (data){
this.success(data);
}
Promise.prototype.then = function (success,error){
this.success = success;
this.error = error;
}
复制代码
class Promise{
constructor(fn){
fn((data)=>{
this.success(data);
},(error)=>{
this.error();
})
}
resolve(data){
this.success(data);
}
reject(error){
this.error(error);
}
then(success,error){
this.success = success;
this.error = error;
console.log(this);
}
}
复制代码
function ajaxPromise(queryUrl){
return new Promise((resolve,reject)=>{
xhr.open('GET',queryUrl,ture);
xhr.send(null);
xhr.onreadystatechange = () =>{
if(xhr.readyState === 4 ){
if(xhr.status === 200){
resolve(xhr.responseText);
}else{
reject(xhr.responseText);
}
}
}
})
}
ajaxPromise('http://www.baidu.com')
.then((value)=>{
console.log(value);
})
.catch((err)=>{
console.error(err);
});
复制代码
then 可使用链式调用的写法缘由在于,每一次执行该方法时老是会返回一个 Promise 对象
readFile('1.txt').then(function(data){
console.log(data);
}).then(function (data){
console.log(data);
return readFile(data);
}).then(function (data){
console.log(data);
}).catch(function (err){
console.log(err);
})
复制代码
Promise.all([p1,p2]).then(function(result){
console.log(result); //[ '2.txt', '2' ]
})
复制代码
无论两个promise谁先完成,Promise.all 方法会按照数组里面的顺序将结果返回
Promise.race([p1,p2]).then(function(result){
console.log(result); //[ '2.txt', '2' ]
})
复制代码
返回一个Promise 实例,这个实例处于resolve状态。
根据传入的参数不一样有不一样的功能:
返回一个Promise实例,这个实例处于reject状态
var Q = require('q');
var fs = require('fs');
function read(filename){
var deferred = Q.defer();
fs.readFile(filename,'utf8',function)(err,data){
if(err){
deferred.reject(err);
}else{
deferred.resolve(data);
}
});
}
read('1.txt1').then(function(data){
console.log(data);
},funtcion(error){
console.error(error);
})
复制代码
module.exports = {
defer(){
var _success,_error;
return {
resolve(data){
_success(data);
},
reject(err){
_error(err);
},
promise:{
then(success,error){
_success = success;
_error = error;
}
}
}
}
}
复制代码
var defer = function () {
var pending = [], value;
return {
resolve: function (_value) {
if (pending) {
value = _value;
for (var i = 0, ii = pending.length; i < ii; i++) {
var callback = pending[i];
callback(value);
}
pending = undefined;
}
},
promise: {
then: function (callback) {
if (pending) {
pending.push(callback);
} else {
callback(value);
}
}
}
};
};
复制代码
实现 promise 标准的库是功能最全,速度最快的一个库
var Promise = require('./bluebird');
var readFile = Promise.promisify(require("fs").readFile);
readFile("1.txt", "utf8").then(function(contents) {
console.log(contents);
})
var fs = Promise.promisifyAll(require("fs"));
fs.readFileAsync("1.txt", "utf8").then(function (contents) {
console.log(contents);
})
复制代码
module.exports = {
promisify(fn){
return function () {
var args = Array.from(arguments);
return new Promise(function (resolve, reject) {
fn.apply(null, args.concat(function (err) {
if (err) {
reject(err);
} else {
resolve(arguments[1])
}
}));
})
}
},
promisifyAll(obj){
for(var attr in obj){
if(obj.hasOwnProperty(attr) && typeof obj[attr] =='function'){
obj[attr+'Async'] = this.promisify(obj[attr]);
}
}
return obj;
}
}
复制代码
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <title>move</title> <style> .square{ width:40px; height:40px; border-radius: 50%; } .square1{ background-color: red; } .square2{ background-color: yellow; } .square3{ background-color: blue; } </style> </head> <body> <div class="square square1" style="margin-left: 0"></div> <div class="square square2" style="margin-left: 0"></div> <div class="square square3" style="margin-left: 0"></div> </body> <script> var square1 = document.querySelector('.square1'); var square2 = document.querySelector('.square2'); var square3 = document.querySelector('.square3'); /*function move(element,target,resolve){ let timer = setInterval(function(){ var marginLeft = parseInt(element.style.marginLeft, 10); if(marginLeft == target){ resolve(); }else{ element.style.marginLeft = ++marginLeft+'px'; } },13); }*/ function move(element,target,resolve){ let current = 0; let timer = setInterval(function(){ element.style.transform=`translateX(${++current}px)`; if(current>target){ clearInterval(timer); resolve(); }; },13); } function animate(element,target){ return new Promise(function(resolve,reject){ move(element,target,resolve); }); } animate(square1,100) .then(function(){ return animate(square2,100); }) .then(function(){ return animate(square3,100); }); </script> </html> 复制代码
let fs = require('fs');
function getNumber(){
return new Promise(function (resolve,reject) {
setTimeout(function(){
let number = Math.random();
if(number >.5){
resolve(number);
}else{
reject('数字过小');
}
},1000);
});
}
function *read(){
let a = yield getNumber();
console.log(a);
let b = yield 'b';
console.log(b);
let c = yield getNumber();
console.log(c);
}
function co(gen){
return new Promise(function(resolve,reject){
let g = gen();
function next(lastValue){
let {done,value} = g.next(lastValue);
if(done){
resolve(lastValue);
}else{
if(value instanceof Promise){
value.then(next,function(val){
reject(val);
});
}else{
next(value);
}
}
}
next();
});
}
co(read).then(function(data){
console.log(data);
},function(reason){
console.log(reason);
});
复制代码
let fs = require('fs');
function readFile(filename){
return new Promise(function (resolve,reject) {
fs.readFile(filename,'utf8',function(err,data){
if(err)
reject(err);
else
resolve(data);
})
});
}
function *read(){
let a = yield readFile('./1.txt');
console.log(a);
let b = yield readFile('./2.txt');
console.log(b);
}
function co(gen){
let g = gen();
function next(val){
let {done,value} = g.next(val);
if(!done){
value.then(next);
}
}
next();
}
复制代码
function Promise(executor) {
let self = this;
self.status = "pending";
self.value = undefined;
self.onResolvedCallbacks = [];
self.onRejectedCallbacks = [];
function resolve(value) {
if (value instanceof Promise) {
return value.then(resolve, reject)
}
setTimeout(function () { // 异步执行全部的回调函数
if (self.status == 'pending') {
self.value = value;
self.status = 'resolved';
self.onResolvedCallbacks.forEach(item => item(value));
}
});
}
function reject(value) {
setTimeout(function () {
if (self.status == 'pending') {
self.value = value;
self.status = 'rejected';
self.onRejectedCallbacks.forEach(item => item(value));
}
});
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循环引用'));
}
let then, called;
if (x != null && ((typeof x == 'object' || typeof x == 'function'))) {
try {
then = x.then;
if (typeof then == 'function') {
then.call(x, function (y) {
if (called)return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, function (r) {
if (called)return;
called = true;
reject(r);
});
} else {
resolve(x);
}
} catch (e) {
if (called)return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : function (value) {
return value
};
onRejected = typeof onRejected == 'function' ? onRejected : function (value) {
throw value
};
let promise2;
if (self.status == 'resolved') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
if (self.status == 'rejected') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onRejected(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
if (self.status == 'pending') {
promise2 = new Promise(function (resolve, reject) {
self.onResolvedCallbacks.push(function (value) {
try {
let x = onFulfilled(value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
self.onRejectedCallbacks.push(function (value) {
try {
let x = onRejected(value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
return promise2;
}
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
}
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
let result = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (data) {
result[i] = data;
if (++count == promises.length) {
resolve(result);
}
}, function (err) {
reject(err);
});
}
});
}
Promise.deferred = Promise.defer = function () {
var defer = {};
defer.promise = new Promise(function (resolve, reject) {
defer.resolve = resolve;
defer.reject = reject;
})
return defer;
}
/** * npm i -g promises-aplus-tests * promises-aplus-tests Promise.js */
try {
module.exports = Promise
} catch (e) {
}
复制代码