晴明的博客园 GitHub      CodePen      CodeWars     

[es6] 积累

将异步控制为顺序执行

使用promise的写法一

        function Say(name) {
            return new Promise(function (resolve, reject) {
                switch (name) {
                    case 'a':
                        setTimeout(()=> {
                            console.log(name);
                            resolve();
                        }, 1000);
                        break;
                    case 'b':
                        setTimeout(()=> {
                            console.log(name);
                            resolve();
                        }, 2000);
                        break;
                    case 'c':
                        setTimeout(()=> {
                            console.log(name);
                            resolve();
                        }, 3000);
                        break;
                    case 'd':
                        console.log(name);
                        resolve();
                        break;
                }
            });
        }

        Say('a')
            .then(()=> { return Say('b') })
            .then(()=> { return Say('c') })
            .then(()=> { return Say('d') })

使用promise的写法二

         function Say() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('a');
                    resolve();
                }, 1000);
            });
        }
        Say().then(() => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(console.log('b'));
                }, 2000);
            });
        }).then(() => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(console.log('c'));
                }, 3000);
            });
        }).then(() => {
            console.log('d');
        })

使用async的写法

        function A() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('a');
                    resolve();
                }, 1000);
            })
        }
        function B() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('b');
                    resolve();
                }, 2000);
            })
        }
        function C() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('c');
                    resolve();
                }, 3000);
            })
        }
        async function Say() {
            await A();
            await B();
            await C();
            console.log('d');
        };
        Say();

如果不需要顺序执行,但需要保证所有异步都执行完毕,可以使用Promise.all 。
但是需要注意这里的Promise.all只是检测是否全部执行成功,以及检测是否抛错,并不能阻止运行,但是能让后续不再resolve。

        let A = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('执行了A')
                    resolve('a');
                }, 1000);
            })
        }
        let B = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('执行了B')
                    //reject('boom')
                    resolve('b');
                }, 2000);
            })
        }
        let C = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('执行了C')
                    resolve('c');
                }, 3000);
            })
        }

        console.time();
        Promise.all([A(), B(), C()]).then((value) => {
            console.log(value);// ["a", "b", "c"]
            console.timeEnd();//约3s
        }, (err) => {
            console.error(err)//boom
            console.timeEnd();//约2s
        });

私有化方法

  • symbol 是用来处理属性名的冲突。但是一个 symbol 属性作为键名时是不能被 Object.keys() 、 Object.getOwnPropertyNames() 获取,所以就造成了一种非私有的内部方法效果。symbol 是不能达到闭包那么好的效果的,因为通过 Symbol.for() 是可以获取同一个 Symbol 值的,获得以后一样是能够访问值。

  • 在 class 中实现私有方法的办法是将方法声明在类外,然后在类中使用 .call() 进行引用。虽然通过这个类对象是不能访问这个方法,但是这个方法其实还是暴露在其他更大的作用域当中的,或者就是使用 symbol 作为方法名。

  • 常规的私有化方法是使用闭包,只对外开发非私有化的部分。

   var Student = (function () {
        var m_staticMaxAge = 120;//定义一个私有的静态属性  

        function ageIsValid(age) { //定义一个私有的静态方法  
            if (age > m_staticMaxAge) {
                throw Error("the property age must be less than " + m_staticMaxAge);
            }
        }

        //返回构造函数,设置一些属性  
        return function (name, age) {

            var m_name, m_age;//把私有属性都放到这里定义  

            //私有属性的 setter 和 getter 都放到这里  
            this.setName = function (name) {

                Student.nameIsValid(name);
                m_name = name;
            };

            this.setAge = function (age) {
                ageIsValid(age);
                m_age = age;
            };

            this.getName = function () {
                return m_name;
            };

            this.getAge = function () {
                return m_age;
            };

            this.setName(name);
            this.setAge(age);
        };
    })();
    //定义公有的方法  
    Student.prototype = {
        show: function () {
            console.log("showcall   name:" + this.getName() + " age:" + this.getAge());
        }
    };

    //定义静态的公有方法  
    Student.nameIsValid = function (name) {
        if (typeof name != 'string') {
            throw Error("property name must me a string value");
        }
    };

    //正常调用  
    var stu = new Student('皮卡丘', 23);
    console.log("name:" + stu.getName() + " age:" + stu.getAge());//name:皮卡丘 age:23
    stu.show();//showcall   name:皮卡丘 age:23



    //报name异常的调用  
    //var stu2 = new Student(1212, 23);//Uncaught Error: property name must me a string value
    //console.log("name:" + stu2.getName() + " age:" + stu2.getAge());
    //stu.show();


    //报age异常的调用  
    //var stu3 = new Student("皮卡丘", 121);//Uncaught Error: the property age must be less than 120
    //console.log("name:" + stu3.getName() + " age:" + stu3.getAge());
    //stu.show();

代替匿名函数的简便写法

    {
        let a = 123;
        console.log(a)//123
    }
    //console.log(a)//a is not defined

    //等价
    (function () {
        let a = 321;
        console.log(a)//321
    })()
    //console.log(a)//a is not defined

Set

Set可存储不重复值,但是其功能也可被对象代替(hash)。

可用于数组去重,如:

    let test = [4, 5, 4, 1, 2, 3, 2];
    let uniqueArray = (arr) => [...new Set(arr)];
    let s = new Set(test);
    console.log(s);//Set(5) {4, 5, 1, 2, 3}
    console.log(...s);//4 5 1 2 3
    console.log(uniqueArray(test));//[4, 5, 1, 2, 3]

Map

普通对象不可以将dom存储为键值,但是Map可以。
类似 Object.create(null),没有原型(prototype)。

for of

可以遍历数组,字符串,Set,Map (总之很吊就是了)
Object.getOwnPropertyNames()
Object.keys()
也只能遍历对象属性名,暂时还没有可以直接遍历对象属性值的方法

for of 并不能遍历对象

    {
        //let oo = {x: 'a', y: 'b', z: 'c'};
        //let oo = {1: 'a', 2: 'b', 3: 'c'};
        let oo = ['a', 'b', 'c'];
        for (let v of oo) {
            console.log(v);
        }
    }
    {
        let oo = {x: 'a', y: 'b', z: 'c'};
        for (let i in oo) {
            console.log(i);
            //console.log(oo.i);//undefined
            console.log(oo[i]);
        }
    }

const

  • const 定义的 Array 中间元素能被修改,const 定义的变量只是持有 Array 的地址,这个变量只是本身不能修改,而对于存在于堆内存中的 Array 本身是可以修改的。
  • 对于 const 声明,只是它的赋值操作被冻结了,而值不会因为 const 而不变。主要是预防在coding过程中的coder因为疏忽对变量的意外修改。
  describe('complex types are NOT fully read-only', () => {

    it('array', () => {
      const arr = [40, 23];
      arr[0] = 42;
      assert.equal(arr[0], 42);
    });
    
    it('object', () => {
      const obj = {x: 1};
      obj.x = 3;
      assert.equal(obj.x, 3);
    });
    
  });

let

在函数里对同名参数进行赋值会报错

    let a = 1;
    (function xx(xx) {
        let a = 2;
        let xx = 'xx';//error
        console.log(a)//2
        console.log(xx)
    })()

块作用域 {}

es6的块级作用域只是针对let 和const声明的变量或函数。

{
  foo(2, 3);
  function foo(a, b) {
    console.log(a, b);
  }
}

foo(1, 2);

// 2 3
// 1 2
//函数作用域提升了

destructuring

describe('destructuring arrays makes shorter code', () => {

  it('extract value from array, e.g. extract 0 into x like so `let [x] = [0];`', () => {
    let [firstValue] = [1];
    assert.strictEqual(firstValue, 1);
  });

  it('swap two variables, in one operation', () => {
    let [x, y] = ['ax', 'why'];
    [x, y] = [y, x];
    assert.deepEqual([x, y], ['why', 'ax']);
  });
  
  it('leading commas', () => {
    const all = ['ax', 'why', 'zet'];
    const [,,z] = all;
    assert.equal(z, 'zet');
  });
  
  it('extract from nested arrays', () => {
    const user = [...['Some', 'One'], 23];
    const [firstName, surname, age] = user;
    
    const expected = 'Some One = 23 years';
    assert.equal(`${firstName} ${surname} = ${age} years`, expected);
  });

  it('chained assignments', () => {
    let c, d;
    let [a, b] = [c, d] = [1, 2];
    assert.deepEqual([a, b, c, d], [1, 2, 1, 2]);
  });

  it('in for-of loop', () => {
    for (let [,a, b] of [[0, 1, 2]]) {
      assert.deepEqual([a, b], [1, 2]);
    }
    
  });

});
describe('destructuring objects', () => {

  it('is simple', () => {
    const {x:x} = {x: 1};
    assert.equal(x, 1);
  });

  describe('nested', () => {
    it('multiple objects', () => {
      const magic = {first: 23, second: 42};
      const {magic: second} = {magic:magic['second']};
      assert.equal(second, 42);
    });
    it('object and array', () => {
      const {z:[,x]} = {z: [23, 42]};
      assert.equal(x, 42);
    });
    it('array and object', () => {
      const [,[{lang}]] = [null, [{env: 'browser', lang: 'ES6'}]];
      assert.equal(lang, 'ES6');
    });
  });
  
  describe('interesting', () => {
    it('missing refs become undefined', () => {
      const {z} = {x: 1, y: 2};
      assert.equal(z, void 0);
    });
  
    it('destructure from builtins (string)', () => {
      const {substr} = '1';
      assert.equal(substr, String.prototype.substr);
    });
  });

});
describe('destructuring also works on strings', () => {

  
  it('destructure every character', () => {
    let [a, b, c] = 'abc';
    assert.deepEqual([a, b, c], ['a', 'b', 'c']);
  });
  
  it('missing characters are undefined', () => {
    const [a, ,c] = 'ab';
    assert.equal(c, void 0);
  });
  
  it('unicode character work too', () => {
    const [,space, coffee] = 'a ☕';
    assert.equal(coffee, '\u{2615}');
  });
  
});

object literal

  describe('The object literal allows for new shorthands', () => {

  const x = 1;
  const y = 2;

  describe('with variables', () => {
    it('the short version for `{x: x}` is {x}', () => {
      const short = {y};
      assert.deepEqual(short, {y: y});
    });
    it('works with multiple variables too', () => {
      const short = {x, y};
      assert.deepEqual(short, {x: x, y: y});
    });
  });
  
  describe('with methods', () => {
    
    const func = () => func;

    it('using the name only uses it as key', () => {
      const short = {func};
      assert.deepEqual(short, {func: func});
    });
    
    it('a different key must be given explicitly, just like before ES6', () => {
      const short = {otherKey:func};
      assert.deepEqual(short, {otherKey: func});
    });
    
    it('inline functions, can written as `obj={func(){}}` instead of `obj={func:function(){}}`', () => {
      const short = {
        inlineFunc(){return 'I am inline'}
      };
      assert.deepEqual(short.inlineFunc(), 'I am inline');
    });
  });
  
});

const short = {
    Func(){return 'I am inline'},
    Func1(){return 'I am inline1'}

};
console.log(short.Func())//'I am inline'
console.log(short.Func1())//'I am inline1'
        let x = 1;
        let y = 2;
        let z = 3
        let short = {x, y, zz: z};
        console.log(short)//{x: 1, y: 2, zz: 3}

template

function


it('inside "${...}" can also be a function call', function() {
      function getDomain(){
        return document.domain;
      }
      var evaluated = `${ getDomain() }`;
      assert.equal(evaluated, 'xx.com');
    });

字符串与变量

var one = 1;
var two = 2;
var three = 3;

function firstValueOnly(strings, firstValue, secondValue) {
    //strings是个数组,接收全部字符串
    console.info(strings);//
    //第二个参数开始,每个参数只代表一个变量
    console.warn(firstValue);//1
    console.warn(secondValue);//2

    return firstValue;
}
firstValueOnly`uno${one}dos${two}`;

function valuesOnly(stringsArray, ...allValues) { // using the new ES6 rest syntax
    console.log(allValues);//[ 1, 2, 3 ]
    return allValues;
}
valuesOnly`uno=${one}, dos=${two}, tres=${three}`;

raw

  it('the `raw` property accesses the string as it was entered', function() {
    function firstChar(strings) {
      return strings.raw;
    }
    assert.equal(firstChar`\n`, '\\n');
  });
  
    describe('`String.raw` as a static function', function(){
    
    it('concats the raw strings', function() {
      var expected = '\\n';
      assert.equal(String.raw`\n`, expected);
    });
    
    it('two raw-templates-string-backslashes equal two escaped backslashes', function() {
      const TWO_BACKSLASHES = '\\\\';
      assert.equal(String.raw`\\`, TWO_BACKSLASHES);
    });
    
    it('works on unicodes too', function() {
      var smilie = '\\u{1F600}';
      var actual = String.raw`\u{1F600}`;
      assert.equal(actual, smilie);
    });
    
  });

arrow function 箭头函数

  • 不可以当做构造函数,也就是说,不可以使用 new 命令,否则会抛出错误。
  • 不可以使用 arguments 对象,该对象在函数体内不存在。
  • 不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

不能用于定义字面量方法

calculator.sum 使用箭头函数来定义,但是调用的时候会抛出 TypeError,因为运行时 this.array 是未定义的,调用 calculator.sum 的时候,执行上下文里面的 this 仍然指向的是 window,原因是箭头函数把函数上下文绑定到了 window 上,this.array 等价于 window.array,显然后者是未定义的。

const calculator = {
    array: [1, 2, 3],
    sum: () => {
        console.log(this === window); // => true
        return this.array.reduce((result, item) => result + item);
    }
};

console.log(this === window); // => true

// Throws "TypeError: Cannot read property 'reduce' of undefined"
calculator.sum();

解决方案

    const calculator = {
        array: [1, 2, 3],
        sum: function () {
            console.log(this === calculator); // => true
            return this.array.reduce((result, item) => result + item);
        }
    };
    console.log(calculator.sum()); // => 6


    //方法简写
    const calculator = {
        array: [1, 2, 3],
        sum() {
            console.log(this === calculator); // => true
            return this.array.reduce((result, item) => result + item);
        }
    };
    console.log(calculator.sum()); // => 6

不能用于定义原型方法

同样的规则适用于原型方法(prototype method)的定义,使用箭头函数会导致运行时的执行上下文错误

function Cat(name) {
    this.name = name;
}

Cat.prototype.sayCatName = () => {
    console.log(this === window); // => true
    return this.name;
};

const cat = new Cat('Mew');
cat.sayCatName(); // => undefined

不能用于定义事件回调函数

箭头函数在声明的时候就绑定了执行上下文,要动态改变上下文是不可能的,在需要动态上下文的时候它的弊端就凸显出来。比如在客户端编程中常见的 DOM 事件回调函数(event listenner)绑定,触发回调函数时 this 指向当前发生事件的 DOM 节点,而动态上下文这个时候就非常有用。

在全局上下文下定义的箭头函数执行时 this 会指向 window,当单击事件发生时,浏览器会尝试用 button 作为上下文来执行事件回调函数,但是箭头函数预定义的上下文是不能被修改的,这样 this.innerHTML 就等价于 window.innerHTML,而后者是没有任何意义的。

const button = document.getElementById('myButton');
button.addEventListener('click', () => {
    console.log(this === window); // => true
    this.innerHTML = 'Clicked button';
});

不能用于定义构造函数

构造函数中的 this 指向新创建的对象,当执行 new Car() 的时候,构造函数 Car 的上下文就是新创建的对象,也就是说 this instanceof Car === true。显然,箭头函数是不能用来做构造函数,会抛出异常。

const Message = (text) => {
    this.text = text;
};
// Throws "TypeError: Message is not a constructor"
const helloMessage = new Message('Hello World!');

=>

describe('arrow functions', function() {

  it('are shorter to write', function() {
    var func = () => {
      return 'I am func'
    };
    assert.equal(func(), 'I am func');
  });

  it('a single expression, without curly braces returns too', function() {
    var func = () => 'I return too';
    assert.equal(func(), 'I return too');
  });

  it('one parameter can be written without parens', () => {
    var func = param => param - 1;
    assert.equal(func(25), 24);
  });

  it('many params require parens', () => {
    var func = (param,param1) => param + param1;
    assert.equal(func(23, 42), 23+42);
  });

  it('body needs parens to return an object', () => {
    var func = () => ({iAm: 'an object'});
    assert.deepEqual(func(), {iAm: 'an object'});
  });

});

this

  it('bound at definition time, use `=>` ', function() {
    var bound = new LexicallyBound();
    var fn = bound.getFunction();
    
    assert.strictEqual(fn(), bound);
  });
 
 
   it('`arguments` doesnt work inside arrow functions', function() {
    var bound = new LexicallyBound();
    var fn = bound.getArgumentsFunction();
    
    assert.equal(fn(1, 2).length, 0);
  });

async

try...catch 两种方式

		async function Say() {
			try {
				await A();
				await B();
				await C();
				console.log('d');
			} catch (e) {
				console.info(e)
			}
		};
		Say();
		async function Say() {
			await A();
			await B();
			await C();
			console.log('d');
		};
		Say().catch((err) => {
			console.log(err)
		});

export

export { default as Affix } from './affix';

export * from xx

default会出现在{}里.
export * 可以全部导出{},包括default.


()=>() //error
()=>({})// return {}
()=>{} //return undefined

let b = {a:'aaa'};
let {a='xx'}=b; //b必须是对象否则报错
a//'aaa' 如果b没有a值,则a会设为默认值'xx'

posted @ 2016-08-31 16:22  晴明桑  阅读(223)  评论(0编辑  收藏  举报