ES6入门 笔记

const命令:

    声明一个只读常量,一旦声明,声明的值就不能改变

    声明的常量和let一样,不可重复声明

本质:并不是变量的值不得改动,而是变量指向的那个内存地址不得改动

const只能保证这个指针固定,它指向的数据结构变不变是无法控制的

对象冻结:object.freeze方法

ES5只有两种声明变量的方法:var 和 function

ES6一共六种声明变量的方法:

let,const,import,class,var,function

var,function声明全局变量,依旧是顶层对象的属性

let,const,classes命令声明的全局变量不属于顶层对象的属性

var a = 1;

window.a;

是正确的

let b = 2

window.b

会报错

现在想要获取顶层变量一般都使用this去获取,但是是有局限性的

1.全局环境中this获取顶层变量,但是在node和es6的环境中,this只能返回当前模块

2.函数中的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象,但是在严格环境下会报未定义的错误

        ----------------这句不是很理解

3.new function('return this')总是返回全局对象,但浏览器用了CSP(Content Security Policy,内容安全策略),那么eval,new Function 这些方法都可能无法使用


解构赋值虽然方便,但是解析并不容易,es6规则:

只要有可能导致解构的歧义,就不能使用圆括号

解构的用途

1.交换变量

let x = 1;

let y = 2;

[x,y] = [y,x];

2.从函数返回多个值

函数只能返回多个值,要想返回很多值,只能将它们放在数组或者对象里返回

3.函数参数的定义

4.提取json数据

5.遍历map解构

const map = new Map();

map.set('first', 'hello');

map.set('second', 'world');

for (let [key, value] of map) {

console.log(key + " is " + value);

}

6.输入模块的指定方法

加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常 清晰。

const { SourceMapConsumer, SourceNode } = require("source-map");


1.es6加强了对Unicode的支持,拓展了字符串对象

codePointAt()

能够正确处理4个字节存储的字节,返回一个字节的码点

codePointAt 方法返回的是码点的十进制值,如果想要十六进制的 值,可以使用 toString 方法转换一下。

let s = 'a' ;

s.codePointAt(0).toString(16) // "20bb7" s.codePointAt(2).toString(16) // "61"

normalize用来将字符的不同表示方式统一为同样的样式

'\u01D1'.normalize() === '\u004F\u030C'.normalize() // true

es6提供了判断一个字符串中是否包含其他字符串的更多方法:

includes(),startsWith(),endWith()

repeat() 返回一个新字符

string.repeat(3);

padStart(),padEnd()

ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度, 会在头部或尾部补全。 padStart() 用于头部补全, padEnd() 用于尾 部补全。

'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba'


RegExp构造函数:

match(),replace().search(),split()

ES6 对正则表达式添加了 u 修饰符,含义为“Unicode模式”,用来正确 处理大于 \uFFFF 的 Unicode 字符。也就是说,会正确处理四个字节的 UTF-16 编码。

/^\uD83D/u.test('\uD83D\uDC2A') // false

 /^\uD83D/.test('\uD83D\uDC2A') // true

除了 u 修饰符,ES6 还为正则表达式添加了 y 修饰符,叫做“粘 连”(sticky)修饰符。 y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上 一次匹配成功的下一个位置开始。不同之处在于, g 修饰符只要剩余位 置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开 始,这也就是“粘连”的涵义。

var s = 'aaa_aa_a'; var r1 = /a+/g; var r2 = /a+/y;

r1.exec(s) // ["aaa"] r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"] r2.exec(s) // null

lastIndex属性:

lastIndex 属性指定每次搜索的开始位置

const REGEX = /a/y;

REGEX.lastIndex = 2;

REGEX.exec('xaya')   // null

REGEX.lastIndex = 3;

const match = REGEX.exec('xaxa');

match.index;

REGEX.lastIndex

mathc用法:

单单一个 y 修饰符对 match 方法,只能返回第一个匹配,必须 与 g 修饰符联用,才能返回所有匹配。

'a1a2a3'.match(/a\d/y) // ["a1"]

'a1a2a3'.match(/a\d/gy) // ["a1", "a2", "a3"]

sticky属性:

与 y 修饰符相匹配,ES6 的正则对象多了 sticky 属性,表示是否设 置了 y 修饰符。

var r = /hello\d/y; 

r.sticky // true

新增flags属性,返回郑子表达式的修饰符

// ES6 的 flags 属性 

// 返回正则表达式的修饰符 /abc/ig.flags 

// 'gi'

正则表达式中,点( . )是一个特殊字符,代表任意的单个字符,但是 行终止符(line terminator character)除外。 以下四个字符属于”行终止符“。 

U+000A 换行符( \n ) 

U+000D 回车符( \r ) 

U+2028 行分隔符(line separator) 

U+2029 段分隔符(paragraph separator)

为了让.可以匹配任意单个字符

引入 /s 修饰 符,使得 . 可以匹配任意单个字符。

/foo.bar/s.test('foo\nbar') // true

这种模式成为dotAll模式,点代表一切字符

所以,正则表达式 还引入了一个 dotAll 属性,返回一个布尔值,表示该正则表达式是否 处在 dotAll 模式。

const re = /foo.bar/s;

re.dotAll

先行断言:

x只有在y前面才匹配     /x(?=y)/

只匹配百分号前的数字  /\d+(?=%)/

先行否定断言

x只有不在y前面才匹配   /x(?!y)/

只匹配不在百分号之前的数字 /\d+(?!%)/

后行断言

与先行断言正好相反

x只有在y后面才匹配      /(?<=y)x/

只匹配美元符号之后的数字   /(?<=\$)\d+/

后行否定断言:x只有不在y后面才匹配  /(?

只匹配不在美元符号后面的数字   /(?

const RE_DOLLAR_PREFIX = /(?<=\$)foo/g; 

'$foo %foo foo'.replace(RE_DOLLAR_PREFIX, 'bar'); // '$bar %foo foo'

上面代码中,只有在美元符号后面的 foo 才会被替换

首先,”后行断言“的组匹配,与正常情况下结果是不一样的。

/(?<=(\d+)(\d+))$/.exec('1053') // ["", "1", "053"] 

/^(\d+)(\d+)$/.exec('1053') // ["1053", "105", "3"]

上面代码中,需要捕捉两个组匹配。没有”后行断言”时,第一个括号是 贪婪模式,第二个括号只能捕获一个字符,所以结果是 105 和 3 。 而”后行断言”时,由于执行顺序是从右到左,第二个括号是贪婪模式, 第一个括号只能捕获一个字符,所以结果是 1 和 053 。

其次,”后行断言”的反斜杠引用,也与通常的顺序相反,必须放在对应 的那个括号之前。

/(?<=(o)d\1)r/.exec('hodor') // null 

/(?<=\1d(o))r/.exec('hodor') // ["r", "o"]

上面代码中,如果后行断言的反斜杠引用( \1 )放在括号的后面,就 不会得到匹配结果,必须放在前面才可以。因为后行断言是先从左到右 扫描,发现匹配以后再回过头,从右到左完成反斜杠引用。

Unicode属性类

\p{...} 和 \P{...}

允许正则表达式匹配符合Unicode某种属性的所有字符

具名组匹配

正则表达式使用圆括号进行组匹配

允许每个匹配组都有一个名字,方便之后的查看和引用

如果要在正则表达式内部引用某个“具名组匹配”,可以使用 \k<组名 > 的写法。

const RE_TWICE = /^(?[a-z]+)!\k$/; 

RE_TWICE.test('abc!abc') // true 

RE_TWICE.test('abc!ab') // false

数字引用( \1 )依然有效

const RE_TWICE = /^(?[a-z]+)!\1$/; 

RE_TWICE.test('abc!abc') // true 

RE_TWICE.test('abc!ab') // false

\1和\k可以同时使用


javaScript准确表示的整数范围在-2^53到2^53之间,超过这个范围,无法精确表示这个值

number.isSafeInteger()判断一个整数是否落在这个范围之内

Ingeter整数类型,只能表示整数,没有位数的限制,任何位数的整数都可以精确表示:1n+3n=4n


参数默认值位置

function f(x, y = 5, z) { return [x, y, z]; }

f() // [undefined, 5, undefined] 

f(1) // [1, 5, undefined] 

f(1, ,2) // 报错 

f(1, undefined, 2) // [1, 5, 2]

有默认值的参数都不是尾参数,无法忽略改参数,如果传入undefined,将触发改参数等于默认值,null则没有这个效果

注意指定了默认值后,函数的length属性将失真,变为0

(function(a){}).length //1

(function(b=1){}).length //0

(function(c,d,e=4){}).length//2

rest参数,用于获取函数的多余参数

function add(...values) {}

函数的length属性,也不包括rest参数

因为参数要先于方法执行,所以遇到以下情况时,会发生错误

function a(value = 070){

    'use strict';

    return value;

}

当给参数附完值之后,进入方法体中,采用严格模式,因为严格模式下八进制是不能带0的,所以报错

为了避免这种情况,采用两种方法:

1.使用全局严格模式

2.把函数抱在一个五参数的立即执行函数里面

const doSomething = (function () { 'use strict'; return function(value = 42) { return value; }; }());


name属性,返回函数名

es6允许使用箭头=>定义函数

var f = v =>v

等价于

var f = function(v){

    return f;

}

var sum = (num1,num2) => num1 + num2;

var sum = function(num1,num2){

    return num1 + num2;

}

使用箭头函数有几个使用注意点

1.this所指的对象不是使用时的对象而是定义时的对象

2.不可以当做构造函数,使用new会报错

3.不可以使用arguments对象,如果要,可以用rest对象代替

4.不可以使用yield命令,因此箭头函数不能做Generator函数


双冒号运算符:

    函数绑定运算符是并排的两个冒号,左边是对象,右边是方法,自动将左边的对象绑定到方法中

    foo::bar 等同于

    bar.bind(foo)

    foo::bar(...arguments);

    bar.apply(foo,arguments);


尾调用优化

    尾调用(tail call)某个函数的最后一步调用了另一个函数

    函数调用会在内存中形成调用记录,比如从A调用B,在A中形成一个B的调用帧(call frame),B中在调用C,会在B中形成C的调用帧,所有调用帧会形成调用栈(call stack)

es6只要使用尾递归就永远不会出现栈溢出

尾调用模式仅在严格模式下生效

蹦床函数(trampoline)

function trampoline(f){

    while(f && f instanceof Function){

        f = f()

}

return f;

}

之前函数参数中是不允许出现尾逗号的,但在新版本中允许尾逗号的出现


const a1=[1,2];

const a2 = a1;

a2[0] = 2;

a1 //[2,2]

直接赋值,获取的是指向a1的指针,改变a2会直接改变a1的值

所以需要使用变通的方法

a2 = a1.concat();

拓展运算符提供了赋值数组的方法

a2 = [...a1]

[...a2] = a1

合并数组:

es5:

[1,2].concat(more)

es6:

[1,2,...more]

在es6中Array,from会将类似数组的对象转为真正的数组

let arrayLike = {

    '0':'a',

    '1':'b',

     '2':'c'

}

let arr2 = Array.from(arrayLike);

类似数组的对象就是拥有length属性的对象,都可以通过array.from转为数组

如果浏览器不支持,则使用array.prototype.slice方法

array.from([1,2,3],(x)=>x*x)

可以使用第二个参数,对其进行处理

array.of可以将一组值转化为数组

Array() // []

Array(3) // [, , ,] 

Array(3, 11, 8) // [3, 11, 8]

上面代码中, Array 方法没有参数、一个参数、三个参数时,返回结 果都不一样。只有当参数个数不少于2个时, Array() 才会返回由参数 组成的新数组。参数个数只有一个时,实际上是指定数组的长度。

copyWithin(target,start,end);

target:替换的位置

start:从哪里替换

end:没有指定则为数组默认长度

[1,2,3,4,5].copywithin(0,3)//[4,5,3,4,5]

fill()方法,填充数组

['a','b','c'].fill(7,1,2)         //['a',7,'c']

includes返回一个布尔值,表示某个函数是否包含给定的值

[1,2,3].includes(2)

使用indexOf的缺点:

    内部严格使用相等运算符(===)进行判断,这会导致对NaN的误判

    [NaN].indexOf(NaN)     // -1


对象的拓展

    const foo = 'value'

    const bar = {foo}        // bar = {foo : 'value'}

相当于

    const bar = {foo: foo}

方法简写:

    const a = {

        method(){

            return "this is a function"

        }

}

相当于

    const a = {

        method() : function(){

            return "this is a function"

        }

    }

name:

    bind方法创造的函数,name会返回bound+name,function创造的函数,name属性返回anonymous属性

相等:

es5中相等方法只有两种,一种是(==)还有一种是严格相等(===)

但都有缺点:

        前者自动转换数据类型,后者NaN不等于自身,+0等于-0

es6增加了object.is(A,B)方法

        与(===)的行为一致,但NaN相等,+0 与 -0不相等

        +0 === -0 //true

         NaN === NaN // false

         Object.is(+0, -0) // false 

         Object.is(NaN, NaN) // true

object.assign()用于方法合并

        const target = {a :1}

        const source1 = {b:2}

        const source2 = {c:3}

        object.assign(target,source1,source3);

        target       //{a:1,b:2,c:3}

如果对象相同,后面会覆盖前面,如果该参数不是对象,会将其转换为对象,然后返回

undefined 和 null 无法转换为对象,所以会报错

const v1 = 'abc'; 

const v2 = true; 

const v3 = 10;

const obj = Object.assign({}, v1, v2, v3);

 console.log(obj); // { "0": "a", "1": "b", "2": "c" }

v1 是字符串,v2是布尔类型,v3是数字,结果只有字符串合入了目标对象,数值和布尔值都会被忽略

这是因为因为只有字符串的包装对象,会产生枚举属性

注意:

object.assign实行的是浅拷贝,就是如果源对象的某个属性是引用,那么拷贝的也是引用,也就是说引用的值改变了,那就都跟着变化

同名属性采用替换原则

Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable // false

另外,ES6 规定,所有 Class 的原型的方法都是不可枚举的。

大多数时候,我们至关心对象自身的属性,多以会用object.keys()代替

_proto_属性,用来读取或者设置当前对象的prototype对象

const obj={

    method:function(){...}

}

obj._proto_=someOtherObj;

最好使用

object.setPrototypeOf()        写操作

object.getPrototypeOf()        读操作

object.create()                          生成操作代替

object.setPrototypeOf是es6正式推荐的设置原型对象的方法

object.getPrototypeOf()获取一个对象的原型对象

super关键字

只能用在对象的方法之中,用在其他地方会报错

对象也可以用解构赋值

但是必须在参数最后一个,也是浅拷贝

克隆完整对象:

    const a = object.assign(

        object.create(object.getPrototypeof(obj))

)

对象的拓展运算符后面也可以跟表达式


NULL传导运算符

const firstName = message?.body?.user?.firstName || 'default';

只要有一个返回null,都会返回undefined


Symbol:保证每一个属性都是独一无二的,是es6引入symbol的原因

JavaScript一共有7种属性

1.null

2.undefined

3.boolean

4.string

5.number

6.object

7.symbol

let s = Symbol();

typeOf s;

symbol函数前不能使用new命令,否则会报错

symbol函数的参数只是表示对当前symbol值的描述,因此相同参数的symbol函数的返回值是不相等的

symbol不能与其他值进行运算

symbol作为属性名时,该属性属于公开属性,不是私有属性


魔术字符串:在代码中多次出现的,与代码形成强耦合的字符串或者数值

一般都会将其改为变量

symbol.for,symbol,keyFor

let s1= Symbol.for('foo')

let s2 = Symbol.for('foo')

s1 === s2   //true

Symbol和Symbol.for的区别是:

        Symbol.for会在全局创建一个供搜索的变量,可以被搜索到,这样每次调用都会是这一个值,但如果不用for,那么每次调用的都会不一样

symbol.keyfor返回的是已登记的symbol类型值的key

Symbol.for为Symbol值登记的名字,是全局环境的,可以在不同的iframe或者service worker中取到同一个值


Singleton模式指的是调用一个类,任何时候返回的都是同一个实例

Symbol.hasInstance:判断是否为该对象的实例

Symbol.isConcatSpreadable:表示该对象用于Array.prototype.concat()是否可以展开

Symbol.species

对象的symbol.species属性,指向当前对象的构造函数。

Symbol.iterator

指向该对象的默认遍历器方法


Set用法:

es6提供了新的数据结构Set

类似于数组,但是成员都是唯一的,没有重复值

const s= new Set()

[2,3,3,6,8].forEach(x=>s,add(x))

let set = new Set()

set.add({});

set.add({});

set.size  //2

由于两个空对象不相等,所以它们被视为两个值

Set实例的操作方法:

        add(value),delete(value),has(value),clear()

WeakSet结构与Set类似,也是不重复的值的集合

但WeakSet的成员只能是对象,es6中WeakSet不可遍历,WeakSet中的数据不会计入内存回收机制,所以删除实例的时候,不用考虑,也不会出现内存泄漏

  Map 键值对

        const map = new Map([['name','a'],['title','Author']]);

        map.size

        map.has('name')

        map.get('name')

       Set 和 Map都可以生成新的Map对象

        Map遍历方法:

            keys,values,forEach,entries()

        map.forEach(function(value, key, map){

                console.log("key:%s,Value:%s",key,value)

        })

        Map 转数组

        const mapDemo = new Map().set(true,7).set({foo:3},['abc'])

        [...mapDemo]    //转换成数组

        数组转Map

        Map转为对象

        strMapToObj(mapDemo)

        对象转map

        strObjToMap({yes:true},{no:false});

        Map转为Json

        strMapToJson(mapDemo);

        Map转为数组JSON

        strMapToArrayJson(mapDemo);

        Json转为Map

        jsonToStrMap('{"yes":true,"no":false}')

    WeakMap弱引用只是健名,而不是键值,键值依然是正常引用

    WeakMap只有四个方法:

        get,set,has,delete

    weakMap部署私有属性

     Proxy:用于修改某些操作的默认行为

           proxy实际上重载了点运算符,用自己的定义覆盖了语言的原始定义

            var proxy = new Proxy(target,handler);

           var proxy = new Proxy({},{

                get :function(target,property){

                        return 35;

                }

            })

let obj = object.create(proxy);

obj.time    //35

Proxy操作一览表

    get(garget,propKey,receiver):拦截器对象属性的读取

    set(target,proKey,value,receiver):拦截器属性的设置  proxy.foo = v

    has(target,proKey):拦截 prokey in proxy操作,返回一个布尔值

     deleteProperty(target,propKey):拦截 delete proxy[propKey],返回一个boolean值

       ownKeys(target):object.getOwnePropertyNames(proxy),Object,getOwnPropertySymbols(proxy),Object.keys(proxy)

        返回一个数组

has()只对in()生效

 construct()用于拦截new命令

deleteProperty()用于拦截delete操作

Reflcet 也是ES6为了操作对象而提供的新的API

Object,defineProperty(obj,name,desc)在无法定义属性时,会抛出一个错误

Reflect对象上可以拿到语言内部的方法

Proxy实现观察值模式

使用observable和observe两个函数


promise:

    就是一个容器,里面保存着某个为了才会结束的时间,从语法上说,promise是一个对象,从它可以获取异步操作的消息

    无法取消promise,一旦新建就会立即执行,无法中途取消。

    如果不设置回调函数,promise无法自己抛出错误,无法反应到外部

    当处于pending状态时,无法得知目前进展到拿一个阶段

   promise.prototype.catch方法是.then(null,regection)的别名,用于指定发生错误时的回调函数

    建议使用().then().catch().catch()

    promise.all()用于将多个promise实例,包装成一个新的promise实例

    var  p = Promise.resolve(''Hello")

    p.then(function(s){

        console.log(s);

     })

    done()总是处于回调链的尾端,保证抛出任何可能出现的错误

    finally()不管对象状态如何,都会执行


Iterator遍历器:

    Iterator接口就是为所有数据结构,提供一种统一的访问机制,即for...of

    yield*:它会调用该结构的遍历器接口

    forEach循环缺点是无法中途跳出,break和return命令都不好用

    for..in循环:数组的健名是数字,但它以字符串来循环

                            会遍历手动添加的其他健

                            在某些情况下,会无顺序的遍历健名

    for..of可以与break,continue,return配合使用

Genenrator.prototype.throw() 可以在函数体

一旦Generator执行过程中抛出错误,且没有被内部捕获,就不会在执行下去了,javascript引擎人呢我这个Generator已经运行结束了。

Generator.prototype.return() 可以返回给定的值,并且终结遍历Generator函数

如果Generator函数内部有try...fninally代码块,那么return方法会推迟到finally代码块执行完在执行

yield*

如果在Generator函数内部,调用另一个Generator函数,默认情况下是没有效果的

这个需要用到yield*,去调用Gneerator函数

如果yield表达式后面跟的是一个遍历器对象,需要在yield表达式后面加上星号,这个就被成为yield*表达式

let obj = { * myGeneratorMethod() { ··· } };

如上述所示,属性前带星号,表示是个Generator函数,等价于

let obj = { myGeneratorMethod: function* () { // ··· } };     

Generator是实现状态机的最佳结构

协程适合用于多任务运行的环境,但是运行的协诚只能有一个,其他协程都处于暂停状态。

JavaScript语言的执行环境是单线程的,如果没有异步编程,更不无法使用

function* asyncJob() { // ...其他代码 var f = yield readFile(fileA); // ...其他代码 }

在asyncJob中,当函数运行到yield时,会将执行权交给其他协程,等到执行权返回再继续执行

将参数出入一个临时函数,临时函数在传入函数体,这个临时函数就叫做thunk函数

thunkify模块

生产环境的转换器建议使用thunkify模块

co模块:用于generator函数的自动执行

处理stream:

    node提供stream模式读写数据,一次只处理数据的一部分,会释放三个事件:

        data事件:下一块数据库已经准备好了

        end事件:整个数据量处理完了

        error事件:发生错误

async函数:

        1.内置执行器

        2.更好的语义

        3.更广的适用性

        4,返回值是promise,这样就可以使用then进行下一步操作

await命令,await命令后面是一个promise对象,如果不是,会被转为一个立即resolve的promise对象

多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发

  let [foo,bar] = await Promise.all(getFoo(),getBar());

如果希望多个请求并发执行,可以使用promise.all方法

fetch方法,远程读取url

fetch(url);

async function logInOrder(urls) { // 并发读取远程URL

const textPromises = urls.map(async url =>

{ const response = await fetch(url); return response.text(); }); // 按次序输出

for (const textPromise of textPromises)

{ console.log(await textPromise); } }

虽然map方法的参数是async函数,但它是并发执行的,应为只有async函数是继发执行,外部不受影响

for awat...of

遍历异步的Iterator接口

异步Generator函数内部可以同时使用await和yield命令,await命令用于将外部操作产生的值输入函数内部,yield命令用于将函数内部的值输出

javascript的四种函数方式,普通型函数,generator函数,async函数,异步generator函数

如果是一系列按照顺序执行的异步操作比如读取文件,写入新内容,在存入硬盘,可以使用async函数

如果是一系列产生相同数据结构的异步操作,可以使用异步generator函数

constructor方法:构造方法,this关键字则代表实例对象

类和模块内部就是严格模式,所以不需要use strice指定运行模式

类必须使用new调用,否则会报错,这个是它跟普通构造函数的一个主要区别

在生产环境,我们可以使用object.getPrototyoeOf方法来获取实例对象的原型


Class表达式

const MyClass = class Me{

    getClassName(){

        return Me,name;

    }

}

上述定义了一个类,但类的名字不是Me,而是MeClass方法

在内部可以使用Me来指代当前类

不存在变量提升:

    类不存在变量提升

    new Foo();

    class Foo{};

上面代码中,Foo类使用在前,定义在后,这样会报错

因为Es6不会自动将类的声明提升到代码头部

this 的指向

   class Logger{

        printName(name = 'there'){

            this,print('hahha')

        }

        print(text){

            console.log(text)

        }

}

const logger = new Logger();

const {printName} = logger;

printName();//会报错,找不到print方法

修改方法,在方法中绑定this

thsi.printName = this.printName.bind(this);

或者使用箭头函数

this.printName = (name = 'there') =>{

    this.print('hello')

}

因为此时this指向的不是内部,而是当前环境

class的静态方法

   所有类中定义的方法都会被实例继承,但是如果前面加了static,那么这个方法就不会被实例继承,而是通过类来调用,这就成为静态方法

类的实例属性:用等号,写入类的定义中

new.target 用在构造函数之中,返回new命令作用于那个构造函数

class可以通过extends关键字实现继承

super关键字

    class A  {}

    class B extends A{

        constructor(){

            super();

        }

    }

子类B的构造函数之中的super(),代表调用父类的构造函数,这个是必须要求

在子类构造函数中,supper指向父类的原型对象,所以定义在父类实例上的方法或者属性,是无法通过super调用的

Mixin:多个对象合成一个新的对象


修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升

core-decorators.js

第三方模块,提供了几种常用的装饰器

@autobind:使得方法中的this对象,绑定原始对象

@readonly:使得属性或方法不可写

@override:检查子类的方法是否正确覆盖了父类的同名方法,如果不正确,会报错

@deprecate:在控制台显示一条信息,显示此方法已被废弃

@supressWarinings:抑制@deprecate导致的输出waring的行为,但是异步代码发出的调用除外

const Foo = {

        foo(){

                console.log('foo')    

        }

}

class MyClass{}

Object.assign(MyClass.prototype,Foo);

let obj = new MyClass();

obj.foo();

通过object.assign方法,可以将Foo方法放进myClass类中

Trait也是一种修饰器,效果与Mixin类似,但是提供了更多功能,比如防止同名方法的冲突,排除混入某些方法,为混入的方法起别名等

@traits(TFoo, TBar::alias({foo: 'aliasFoo'}))

@traits(TExample::excludes('foo','bar')::alias({baz:'exa mpleBaz'}))

以上为起别名和排除方法

Babel转码器的支持

在线转码网址:

https://babeljs.io/repl/


Modeule

在Es6之前,javascript一直没有模块这个概念,所以用的是CommonJs和AMD两种,在es6之后,有了模块功能,可以在编译时就确定模块的依赖关系,以及输入和输出的变量,CommonJs和AMD都只能在运行时确定这些东西,

// ES6模块 import { stat, exists, readFile } from 'fs';

表示只加载fs中的这三个方法,其他的都不加载

ES6自动采用严格模式

1.变量必须声明后使用

2.函数的参数不能有同名属性

3.不能使用with语句

4.不能对只读属性赋值,否则报错

5.不能使用前缀0表示八进制数,否则报错

6.不能给只读属性赋值

7.不能删除不能删除的属性

8.eval不会再外层作用域引入变量

9.arguments和eval不能重新被赋值

10.argument不会自动反应函数参数的变化

11.不能使用argument.callee

12.不能使用argument.caller

13.禁止this指向全局对象

14.不能使用 fn.caller 和 fn.arguments 获取函数调用的堆栈 

15.增加了保留字(比如 protected 、 static 和 interface )

export命令

    模块功能主要由两个命令构成,export和import.

    export命令主要规定模块的对外接口

    import用于输入其他模块提供的功能


默认情况下,浏览器试同步加载javaScript脚本,即渲染引擎遇到

打开对应属性,就会异步加载

defer和async属性的区别:

    前者要等到整个页面正常渲染结束,才会执行

    后者一旦下载完,渲染引擎就会中断渲染,执行这个脚本后,在继续渲染

    defer是渲染完就执行

    async是下载完就执行

如果有多个defer脚本,会按照它们在页面出现的顺序加载,多个async脚本是不能保证加载顺序的


模块加载规则:

    

需要加入type="module"才可以

模块加载默认为defer模式

模块一旦使用了async属性,

你可能感兴趣的:(ES6入门 笔记)