es6学习笔记2-—symbol、变量与作用域

1、新的字符串特性

标签模板:

  • String.raw(callSite, ...substitutions) : string

    用于获取“原始”字符串内容的模板标签(反斜杠不再是转义字符):

      > String.raw`\` === '\\'
      true

Unicode 和码点:

  • String.fromCodePoint(...codePoints : number[]) : string

    将数字值转换成 Unicode 码点字,然后返回由码点构成的字符串。

  • String.prototype.codePointAt(pos) : number

    返回在从位置 pos 处开始的码点的数字值(由一个或者两个 JavaScript 字符组成)。

  • String.prototype.normalize(form? : string) : string

    不同的码点组合可能看起来是一样的。 Unicode 标准化 将它们修正为相同的标准值。这对相等比较和字符串搜索很有帮助。对于一般的文本,建议使用 NFC形式。

查找字符串:

  • String.prototype.startsWith(searchString, position=0) : boolean

    position 参数指定了字符串的开始搜索位置。

  • String.prototype.endsWith(searchString, endPosition=searchString.length) : boolean

    endPosition 指定了字符串的结束搜索位置。

  • String.prototype.includes(searchString, position=0) : boolean

    从字符串 position 位置开始搜索,是否包含 searchString 子串。

重复字符串:

  • String.prototype.repeat(count) : string

    返回重复指定次数的字符串。

  • padStart用于头部补全,padEnd用于尾部补全。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
//**********************
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
//**********************
var s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true
//**********************
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
// true

var s = "𠮷";

s.length // 2
s.charAt(0) // ''
s.charAt(1) // ''
s.charCodeAt(0) // 55362
s.charCodeAt(1) // 57271

2、symbol

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,前六种是:Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

let s = Symbol();

typeof s
// "symbol"

 

用途1:唯一属性键

Symbol 主要用作唯一属性键 - 一个 symbol 对象不会与任何其他属性键(另一个 symbol 对象或者字符串)冲突。例如,你可以将 Symbol.iterator 作为某个对象的键(键值是一个方法),使其变得可迭代(可以通过 for-of 或者其他语言机制来迭代,更多相关内容可以在有关迭代的章节找到):

const iterableObject = {
    [Symbol.iterator]() { // (A)
        const data = ['hello', 'world'];
        let index = 0;
        return {
            next() {
                if (index < data.length) {
                    return { value: data[index++] };
                } else {
                    return { done: true };
                }
            }
        };
    }
}
for (const x of iterableObject) {
    console.log(x);
}
// Output:
// hello
// world

在行 A 处, symbol 对象用作键,键值是一个方法。这个唯一的键使得该对象可迭代,可用于 for-of 循环。

用途2:用常量代表特殊的含义

在 ECMAScript 5 中,你可能会使用字符串来表示一些特殊的含义,比如颜色。在 ES6 中,可以使用 symbol ,因为 symbol 总是唯一的:

const COLOR_RED    = Symbol('Red');
const COLOR_ORANGE = Symbol('Orange');
const COLOR_YELLOW = Symbol('Yellow');
const COLOR_GREEN  = Symbol('Green');
const COLOR_BLUE   = Symbol('Blue');
const COLOR_VIOLET = Symbol('Violet');

function getComplement(color) {
    switch (color) {
        case COLOR_RED:
            return COLOR_GREEN;
        case COLOR_ORANGE:
            return COLOR_BLUE;
        case COLOR_YELLOW:
            return COLOR_VIOLET;
        case COLOR_GREEN:
            return COLOR_RED;
        case COLOR_BLUE:
            return COLOR_ORANGE;
        case COLOR_VIOLET:
            return COLOR_YELLOW;
        default:
            throw new Exception('Unknown color: '+color);
    }
}

3 陷阱:不能将 symbol 强制转换成字符串

将 symbol 强制(隐式地)转换成字符串会抛出异常:

const sym = Symbol('desc');

const str1 = '' + sym; // TypeError
const str2 = `${sym}`; // TypeError

只能通过显示的方式转换:

const str2 = String(sym); // 'Symbol(desc)'
const str3 = sym.toString(); // 'Symbol(desc)'

禁止强制转换能够避免一些错误,但是也使得 symbol 的使用变得复杂起来。

4 哪些跟属性相关的操作能感知到 symbol 键?

下面的操作能感知到 symbol 键:

  • Reflect.ownKeys()
  • 通过 [] 访问属性
  • Object.assign()

下面的操作会忽略掉 symbol 键:

  • Object.keys()
  • Object.getOwnPropertyNames()
  • for-in 循环

ES6 新增了两个定义变量的关键字:let 与 const,它们几乎取代了 ES5 定义变量的方式:var

3 变量与作用域

let

let 语法上非常类似于 var,但定义的变量是语句块级作用域,只存在于当前的语句块中,不存在变量提升var 拥有函数作用域。

在如下的代码中,let 定义的变量 tmp 只存在于行 A 开始的语句块中:

function order(x, y) {
    if (x > y) { // (A)
        let tmp = x;
        x = y;
        y = tmp;
    }
    console.log(tmp === x); // ReferenceError: tmp is not defined
    return [x, y];
}
一些规则:
  • 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。
  • let不允许在相同作用域内,重复声明同一个变量。

const

const 和 let 类似,但是定义变量时必须初始化值,并且是只读的。

const foo;
    // SyntaxError: missing = in const declaration

const bar = 123;
bar = 456;
    // TypeError: `bar` is read-only

规则:

  • const的作用域与let命令相同:只在声明所在的块级作用域内有效。
  • const 声明一个只读的常量。一旦声明,常量的值就不能改变。一旦声明变量,就必须立即初始化,不能留到以后赋值。
  • const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
  • const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。

3 定义变量的方式

下面的表格对比了在 ES6 中定义变量的 6 种方式:

 HoistingScopeCreates global properties
var Declaration Function Yes
let Temporal dead zone Block No
const Temporal dead zone Block No
function Complete Block Yes
class No Block No
import Complete Module-global No


posted @ 2016-07-14 11:38  huansky  阅读(1471)  评论(0编辑  收藏  举报