zoukankan      html  css  js  c++  java
  • 《ES6标准入门》学习笔记

            //1,声明关键字:const、let
                const plus1 = a => a + 1;
                const mult2 = b => b * 2;
                console.log(mult2(plus1(1)));
    
                //plus1 = 2;//const声明的变量的值不能重新被赋值
                            //let声明一个块级作用域,只在其所在包含块中有效。
            //2 箭头函数=>
    
            //箭头函数
            /*
            1.参数 => 返回值
            2.this绑定(其内部并没有this,因此也不能作为构造函数和new构造器组合使用)
            3.等同于匿名函数
            4. 不能使用call、apply、bind方法
             */
            console.log([1,2,3].map(x => x +1));//[2,3,4]
    
            //箭头函数绑定this
            let handler = {
                id: '123456',
                init:function () {
    
                    //因为箭头函数中没有this,所以下行代码中的this为init方法的this,指向handler
                    document.addEventListener('click', event => this.doSomething(event.type), false);
                },
                doSomething: function (type) {
                    console.log("Handling " + type + " for " + this.id);
                }
            };
            handler.init();
    
            //箭头函数练习
            function foo() {
                return () => {
                    return () => {
                        return () => {
                            console.log("id:", this.id);
                        }
                    }
                }
            }
            foo.call({id: "zgatry"})()()();//输出zgatry,这里通过.call把foo函数内部的this指向了{id:"zgatry"}对象
    
            //箭头函数也不像其他函数一样自带类数组arguments
            function fn() {
                setTimeout(() => {
    
                    //这里的arguments其实是fn函数的arguments
                    console.log("args:", arguments);
                }, 1000);
            }
            fn("zgatry", 2, 3, 4);//输出"zgatry", 2, 3, 4
    
            //箭头函数总结:主要用于解决this绑定、简化函数提升可读性问题。<<----个人理解
    
            //关于this绑定的问题,ES7提出了“::”this绑定符。它会将符号左边的对象作为右边代码的this指向。该符号返回的是原对象,可以进行链式写法。
    
    
            //尾调用优化:在一个函数的最后一步调用另一个函数
            //函数调用——在内存形成调用记录(调用帧)——嵌套调用时,外部函数必须等内部的函数执行完毕,它的调用帧才会消失。它们的组合形成“调用栈”。
            //所以调用帧最好是及时清除,否则对内存是极大的消耗。
            //尾调用优点:及时清除外部函数的调用帧,减少调用帧的个数。
    
            //注意:尾调用优化在严格模式才会生效
            //例如:
            function plusThenMult(a, b) {
                var val = a + b;
                console.log("加的结果", val);
                return mult(a, b);
            }
            function mult(a, b) {
                var val = a * b;
                console.log("乘的结果", val);
            }
            plusThenMult(1,2);
    
            //尾调用不一定出现在尾部,只要求是最后一步。
    
            //尾调用拓展——尾递归, 还涉及到复杂度
            //阶乘函数的例子
    
            //尾递归的方式
            function factorial(n, total) {
                if(n === 1) return total;
                return factorial(n - 1, n * total);
                //只有一个调用帧,复杂度O(1);
            }
            //正常的方式
            function factor2(n) {
                if(n === 1) return 1;
                return n * factor2( n - 1);
                //形成多层调用帧,容易发生栈溢出错误stack overflow
                //形成n层调用帧,复杂度O(n);
            }
    
            //尾调用优化对递归操作意义大
    
            //上面使用尾调用优化的阶乘函数传参怪怪的,我要得到5的阶乘,还要这样传 (5, 1);
            //使用ES6的函数默认值就优雅多了
            
            //改写
            function factorial(n, total = 1) {  //默认值只有在total为undefined时才生效
                if(n === 1) return total;
                return factorial(n - 1, n * total);
                //只有一个调用帧,复杂度O(1);
            }
            console.log("5的阶乘:",factorial(5));//输出120
    
            //Symbol
            /*
            新的原始数据类型——独一无二——由Symbol函数生成——类似于字符串
            */
            let s = Symbol();
            console.log(typeof s);
            let s1 = Symbol('foo'); //Symbol传参用以与其他值区分,解释该值。
    
            let s2 = Symbol('bar');
            s1.toString();
            s2.toString();
            console.log(s1);
            console.log(s2);
            
            //主要用于对象的属性名的标示符,避免属性名重复导致属性被覆盖的问题
            //增强的对象写法
            let s3 = Symbol('test'); 
            let obj = {
                [s](args) {
                    console.log(1);
                },
                name: 'zgatry'
            }
            console.log(obj[s]);
    
            //ES6的class类————ES5的构造函数的一层包装
    
            class userMethod {
                constructor (ele) {
                    this.$class = ele;
                }
                renderHtml () {
                    console.log('渲染用户页面');
                    return true;
                }
            }
    
            let userInfo = new userMethod('zgatry');
            userInfo.renderHtml();
            console.log(userInfo.$class);
    
            //所有的实例共享一个原型对象
            let user1 = new userMethod('aoao');
            let user2 = new userMethod('aobo');
    
            console.log("相同的原型对象?", user1.__proto__ === user2.__proto__);
    
            //实例为原型添加方法<<---不推荐使用
            user1.__proto__.plus = function (val){
                return val + 1
            }
            console.log("原型方法添加成功", user2.plus(2));
            
            //不存在变量提升:ES不会把变量声明提升到代码头部      let命令也是不提升的
            // new Foo();//Foo is not defined
            // class Foo{}
            //上面的特性与继承有关:为了保证子类在父类之后定义。
            {
                let Foo = class {};
                class Bar extends Foo {     //通过extend关键字进行继承
    
                }
            }
            //关于继承
            //继续使用上面的userMethod的类
            class VIPuser extends userMethod {
                constructor($class, VIPnumber) {
                    super($class);  //调用父类的constructor(x, y);   不调用该方法会报错   不加$class则继承不到父类的属性但this可以用了
                    this.VIPnumber = VIPnumber; //子类没有this,需要通过super关键字,它指代了父类的实例(即父类的this对象)
                }
            }
    
            let VIP1 = new VIPuser('bobo', 1);
            console.log(VIP1.$class, VIP1.renderHtml(), VIP1.VIPnumber);
            
    
            //两条继承链的解释和说明
            //例子
            class A {}
            class B extends A {}
            //1.作为对象,B的原型(__proto__)就是父类A;
            B.prototype.__proto__ = A.prototype;
            //2.作为构造函数, 子类B的原型(prototype属性)是父类的实例.
            B.prototype = new A();
    
            //class的存值函数和取值函数,为某个属性添加取值和存值, 捕获取值和存值行为
            class MyClass {
                constructor() {
                    //...
                }
                get prop() {
                    console.log('getter');
                }
                set prop(value) {
                    console.log('setter:', value);
                }
            }
            var inst = new MyClass();
            inst.prop = 123;
            inst.prop;
    
            //ES6在类和模块的内部默认使用严格模式
            
            //Generator方法   在方法前加*表示    暂不拓展
    
            //静态方法与静态属性     在方法前加static表示
            /*
                1.静态方法不会被实例继承
                2.静态方法可以被子类继承
                3.只能直接通过类调用。
                4.但也可以通过super对象调用(因为super是父类的this)
            */
            class Foo {
                static classMethod () {
                    return 'hello'
                }
            }
            class Bar extends Foo {
                static classMethod () {
                    return super.classMethod() + ', too';
                }
            }
            console.log(Bar.classMethod());
            
            //静态属性
            //两种无效的写法
            // class Foo {
            //     //写法一
            //     prop:2
    
            //     //写法二
            //     static prop:2
            // }
    
            //实例属性的新写法  ES7
            // class Myclass {
            //     myProp = 42;
            //     constructor () {
            //         console.log(this.myProp);//42
                    
            //     }
            // }
            // class Myclass {
            //     static myStaticProp = 42;
            //     constructor () {
            //         console.log(Myclass.myProp);//42
                    
            //     }
            // }
    
            /*
            模块
            Module语法是JavaScript的标准语法
            1.使用import替代require
            2.使用export替代module.exports
    
            //bad
            const moduleA = require('moduleA');
            const func1 = moduleA.func1;
            const func2 = moduleA.func2;
    
            //good 
            import {func1, func2} form 'moduleA';
    
            //CommonJs 写法
            var React = require('react');
            var Breadcrumbs = React.createClass({
    			render () {
    				return <nav />;
    			}
            });
            module.exports = Breadcrumbs;
    
            //ES6写法
            import React from 'react';
            const Breadcrumbs = React.createClass({
    			render () {
    				return <nav />;
    			}
            });
            export default Breadcrumbs;	//只有一个输出值的时候使用default,多个值就不适用。
            */
    
            /*
    
    		异步操作和async函数
    
    		ES6前异步编程的方法
    		1.回调函数
    		2.事件监听
    		3.发布-订阅
    		4.promise对象
    
    		回调函数
    		-->>回调函数噩梦:多个回调函数嵌套的问题上,比如说依次读取多个文件,就会出现多重嵌套,代码很快就会乱做一团。
    		fs.readFile(fileA, function(err, data) {
    			fs.readFile(fileB, function(err, data) {
    				//...
    			})
    		})
    		
    		Promise
    		Promise允许将回调函数的横向加载改成纵向加载。
    		Promise 提供了then方法用于执行回调函数,catch方法捕捉执行过程中跑出的错误。
    		缺点:代码冗余,缺乏语义化。
    		var readFile = require('fs-readfile-promise');
    
    		readFile(fileA)
    		.then(function(data) {
    			console.log(data.toString());
    		})
    		.then(function() {
    			return readFile(fileB);
    		})
    		.then(function(data) {
    			console.log(data.toString);
    		})
    		.catch(function(err) {
    			console.log(err);
    		});
    
            基于Promise对象的自动执行器
            var fs = require('fs');
    
            var readfile = function(fileName) {
                return new Promise(function (resolve, reject) {
                    fs.readFile(fileName, function(error, data) {
                        if(error) reject(error);
                        resolve(data);
                    });
                });
            };
            var gen = function* () {
                var f1 = yield readFile('/etc/fstab');
                var f2 = yield readFile('/etc/shells');
                console.log(f1.toString());
                console.log(f2.toString());
            };
    
            //手动执行Generator函数
            var g = gen();
    
            g.next().value.then(function(data) {
                g.next().value.then(function(data) {
                    g.next(data);
                });
            });
    
            //手动操作其实就是通过then层层执行回调函数。
    
            //现在来写自动执行器
    
            var run = function(gen) {
                var g = gen();
                function next() {
                    var result = g.next(data);
                    if(result.done) return result.value;
                    result.value.then(function(data) {
                        next(data);
                    });
                }
                next();
            };
    
            //这样Generator函数就可以自动执行了。
            run(gen);
    
            async函数———Generator函数的语法糖
    
            用async实现读取两个文件的范例:
            
            var asyncReadFile = async function() {
                var f1 = await readFile('/etc/fatab');
                var f2 = await readFile('/etc/shells');
                console.log(f1.toString());
                console.log(f2.toString());
            };
        
            var result = asyncReadFile();
    
            
    
            */
    

    editTime: 2016/10/09

  • 相关阅读:
    [JSOI2008]Blue Mary开公司[李超线段树]
    线段树分治
    满汉全席[2-SAT]
    「一本通 3.5 练习 5」和平委员会
    2-SAT问题
    2019/04/06 BJ省选模拟DAY1
    构造题【随时更
    文本编辑器vim/vi——命令模式
    指令——cat
    指令——history
  • 原文地址:https://www.cnblogs.com/foxNike/p/6378038.html
Copyright © 2011-2022 走看看