JS-Javascript实现

一个完整的JavaScript的实现由三个部分组成:

  • 核心:ECMAScript
  • 文档对象模型:DOM
  • 浏览器对象模型:BOM

ECMAScript

什么是 ES
ECMAScript(简称ES)是由ECMA-262定义的。

ES 与 JS
ES可以理解为是JavaScript的一个标准。实际上,JavaScript是ECMA-262标准的实现和扩展。

ES与Web浏览器
ES与浏览器没有依赖关系。 Web浏览器只是ES实现可能的宿主环境之一,其他宿主环境包括node和Adobe flash。

ES6新增功能

ES6即ECMAScript的第6版。

let

let的特性 let-Javascript MDN

  1. let和const不会在全局声明时创建window对象的属性;而位于函数或代码顶部的var声明会给全局对象新增属性
var x = 'global'
let y = 'global'
console.log(this.x) // "global"
console.log(this.y) // undefined
  1. let声明的变量、语句或者表达式的作用域限制在块级作用域中;var声明的变量只能是全局或者整个函数块的
var a = 1
var b = 2

if (a === 1) {
  var a = 11 // the scope is global
  let b = 22 // the scope is inside the if-block

  console.log(a) // 11
  console.log(b) // 22
}

console.log(a) // 11
console.log(b) // 2
  1. 初始化:let在编译时才初始化
  2. 可以用来模仿私有成员,在处理构造函数时,通过let声明而不是闭包来创建一个或多个私有成员
var Thing
{
  let privateScope = new WeakMap()
  let counter = 0
  Thing = function () {
    this.someProperty = 'foo'
    privateScope.set(this, {
      hidden: ++counter,
    })
  }
  Thing.prototype.showPublic = function () {
    return this.someProperty
  }
  Thing.prototype.showPrivate = function () {
    return privateScope.get(this).hidden
  }
}

console.log(typeof privateScope) // "undefined"
var thing = new Thing()
console.log(thing) // Thing {someProperty: "foo"}
thing.showPublic() // "foo"
thing.showPrivate() // 1
  1. 在同一个函数或块作用域中重复声明同一个变量会引起SyntaxError
// 在 switch 语句中只有一个块
let x = 1
switch (x) {
  case 0:
    let foo
    break
  case 1:
    let foo // SyntaxError for redeclaration.
    break
}
// 解决方法:一个嵌套在 case 子句中的块会创建一个新的块作用域的词法环境
let x = 1
switch (x) {
  case 0: {
    let foo
    break
  }
  case 1: {
    let foo
    break
  }
}
  1. 暂存死区与变量提升:let和const不存在变量提升,直到它们的定义被执行时才初始化;在变量初始化前访问该变量会导致ReferenceError,该变量处在一个自块顶部到初始化处理的“暂存死区”中
function do_something() {
  console.log(bar) // undefined
  console.log(foo) // ReferenceError
  var bar = 1
  let foo = 2
}
// 在同一行,这个if块中的foo已经在词法环境中被创建了,但是还没有到达(或者终止)它的初始化(这是语句本身的一部分)
// 这个if块里的foo还依旧在暂存死区里
function test() {
  var foo = 33
  {
    let foo = foo + 55 // ReferenceError
  }
}
test()
  1. 暂存死区与typeof:通过var声明的变量有初始化值undefined,和未声明变量的typeof都为undefined;而let,使用typeof检测在暂存死区中的变量, 会抛出ReferenceError异常
console.log(typeof undeclaredVariable) //打印出 undefined
console.log(typeof undeclaredVariable) //打印出 undefined
var varVariable
console.log(typeof i) //引发异常 ReferenceError: Cannot access 'i' before initialization
let i = 10

const

const声明一个只读的常量。一旦声明,变量指向的那个内存地址不得改动(不是变量值不能改变),且声明时必须立即初始化,不能留到以后赋值。const的作用域与let命令相同:只在声明所在的块级作用域内有效。
对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。
但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。如果真的想将对象或对象属性冻结,应该使用Object.freeze方法。

const foo = {}; // const foo = []同理,可以正常使用push等功能
foo.prop = 123; // 为foo添加一个属性,可以成功
console.log(foo.prop); //123
foo = {}; // 将foo指向另一个对象,就会报错

Class

Class ES2015
类的数据类型就是函数,类本身就指向构造函数

import

解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

let a = 1;
let b = 2;
let c = 3;
// 等价于
let [a, b, c] = [1, 2, 3];
 
let [ , third] = ["foo", "bar", "baz"];
third // "bar"
 
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
 
let [x, y, ...z] = ['a'];
x // "a"
y // 变量解构不成功,赋值为undefined
z // 数组解构不成功,赋值为[]

解构赋值允许指定默认值,只有当一个数组成员严格等于undefined,默认值才会生效:

let [foo = true] = []; // foo = true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [q = 1, w = 'b'] = ['a', undefined]; // q='a', w='b'
let [e = 1] = [null]; // e = null
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章