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 种方式:

  Hoisting Scope Creates 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


你可能感兴趣的:(es6学习笔记2-—symbol、变量与作用域)