首页 > 代码库 > ECMAScript学习笔记

ECMAScript学习笔记

let和const命令

  • let声明的作用域为代码块,不存在变量提升。
  • let不允许在相同的作用域内,重复声明同一个变量。
  • const用法与let类似,区别是const声明的变量是常量。

为什么需要块级作用域?

  1. 内层变量可能会覆盖外层变量
  2. 用来计数的循环变量泄漏为全局变量

对象的解构赋值

默认值生效的条件是,对象的属性值严格等于undefined。

以下三种解构赋值不得使用圆括号

  • 变量声明语句中,不能带有圆括号
  • 函数参数中,模式不能带有圆括号
  • 赋值语句中,不能将整个模式,或嵌套模式中的一层,放在圆括号中

可以使用圆括号的情况

  • 赋值语句的非模式部分,可以使用圆括号

变量解构赋值的用途:

  1. 交换变量的值
  2. 从函数返回多个值
  3. 函数参数的定义
  4. 提取JSON数据
  5. 函数参数的默认值
  6. 遍历Map结构
  7. 输入模块的指定方法

字符串的扩展

函数的扩展

什么是尾递归(Tail Call):就是指某个函数最后一步调用另一个函数。函数调用会在内存形成一个“调用记录”,又称“调用帧”,保存调用位置和内部变量等信息。尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息已经不会再用到了,只要直接用内层函数取代外层函数的调用帧就可以了。

fibonacci数列的例子说明如下:

  1. function Fibonacci(n) {
  2. if (n <= 1) {
  3. return 1;
  4. };
  5. return Fibonacci(n - 1) + Fibonacci(n - 2);
  6. }
  7. console.log(Fibonacci(10));
  8. function FibonacciTailCall(n) {
  9. var ac1 = arguments.length <= 1 || arguments[1] === undefined ? 1 : arguments[1];
  10. var ac2 = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2];
  11. if (n <= 1) {
  12. return ac2;
  13. }
  14. return FibonacciTailCall(n - 1, ac2, ac1 + ac2);
  15. }
  16. console.log(FibonacciTailCall(1000));

对象的扩展

ES6允许在对象中只写属性名,不写属性值,此时属性值等于属性名所代表的变量。

描述对象的 enumerable 属性,成为“可枚举性”,如果该属性为 false ,就表示某些操作会忽略当前属性。 ES5 有三个操作会忽略 enmerbale 为 false 的属性。

  • for...in 循环:只遍历对象自身和继承的可枚举属性
  • Object.keys() :返回对象自身的所有可枚举属性的键名
  • JSON.stringify() :只串化对象自身的可枚举的属性
    ES6 新增了一个操作 Object.assign() ,会忽略 enumerablefalse 的属性,只拷贝对象自身的可枚举属性。

Symbol

ES5 的对象属性名都是字符串,容易造成属性名的冲突。如果有一种机制保证每个属性的名字都是独一无二,这样就从根本上防止了属性名的冲突,这就是ES6引入Symbol的原因。

Proxy和Reflect

Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程(meta programming)”,即对编程语言进行编程。

二进制数组

由于WebGL是指浏览器与显卡之间的通信接口,需要满足大量的、实时的数据交换,所以它们之间的通信必须是二进制的。
二进制数组由三类对象组成:

  • ArrayBuffer对象:代表内存之中的一段二进制数据,可以通过“视图”进行操作。“视图”部署了数组接口,这意味着,可以用数组的方法操作内存。
  • TypeArray视图:共包括9种类型的视图,比如Uint8Array数组视图、Int16Array数组视图、Float32Array数组视图
  • DataView视图:可以自定义符合格式的视图,比如第一个字节是Uint8、第二三个字节是Int16、第四个字节是Float32Array数组视图等。

简单来说,ArrayBuffer对象代表原始的二进制数据,TypeArray视图用来读写简单类型的二进制数据,DataView视图用来读写复杂的二进制数据。ArrayBuffer对象代表存储在二进制数据的一段内存,它不能直接读写,只能通过视图读写,视图的作用是以指定格式解读二进制数据。

TypedArrary数组的构造函数,可以接受另一个TypedArray实例作为参数。此时生成的新数组,只是复制了参数数组的值,对应的底层内存是不一样的。新数组会开辟一段新的内存存储数据,不会在原数组的内存之上建立视图。

如果想在遍历操作中,同步改变原来的Set结构,目前并没有直接的方法,但有两种变通反复。一种是利用原Set结构映射出一个新的结构,然后赋值给原来的Set结构;另一种是利用 Array.from 方法

Tips: Map中,只有对同一对象的引用,Map结构才将其视为同一个键

Class

ES5的继承,实质是先创造了子类的实例对象 this ,然后再将父类的方法添加到 this 上面( Parent.apply(this) )。ES6的继承机制安全不同,实质是先创造父类的实例对象 this (所以必须先调用 super 方法),然后再用子类的构造函数修改 this 。

Class作为构造函数的语法糖,同时有prototype属性和proto属性,因此存在两条继承链。

  1. 子类的proto属性,表示构造函数的继承,总是指向父类。
  2. 子类 prototype 属性的 proto 属性,表示方法的继承,总是指向父类的 prototype 属性。
  1. class A {
  2. }
  3. class B extends A {
  4. }
  5. B.__proto__ === A // true
  6. B.prototype.__proto__ === A.prototype // true


来自为知笔记(Wiz)


ECMAScript学习笔记