zoukankan      html  css  js  c++  java
  • symbol,箭头函数

    Symbol

    概述

    • 引入Symbol的原因:保证每个属性的名字都是独一无二的,这样就从根本上防止属性名的冲突。

    • 原始数据结构Symbol,表示独一无二的值。

    • Symbol值通过Symbol函数生成。

      let s = Symbol();
      
      typeof s
      // "symbol"
      
    • 注意,Symbol函数前不能使用new命令,否则会报错。这是由于Symbol值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

    • Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

    let s1 = Symbol('foo');
    let s2 = Symbol('bar');
    
    s1 // Symbol(foo)
    s2 // Symbol(bar)
    
    s1.toString() // "Symbol(foo)"
    s2.toString() // "Symbol(bar)"
    

    s1s2是两个 Symbol 值。如果不加参数,它们在控制台的输出都是Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。

    • 如果 Symbol 的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个 Symbol 值。

      const obj = {
        toString() {
          return 'abc';
        }
      };
      const sym = Symbol(obj);
      sym // Symbol(abc)
      
    • 注意,Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。

      / 没有参数的情况
      let s1 = Symbol();
      let s2 = Symbol();
      
      s1 === s2 // false
      
      // 有参数的情况
      let s1 = Symbol('foo');
      let s2 = Symbol('foo');
      
      s1 === s2 // false
      

      上面代码中,s1s2都是Symbol函数的返回值,而且参数相同,但是它们是不相等的。

    • Symbol 值不能与其他类型的值进行运算,会报错。

      let sym = Symbol('My symbol');
      
      "your symbol is " + sym
      // TypeError: can't convert symbol to string
      `your symbol is ${sym}`
      // TypeError: can't convert symbol to string
      

      但是,Symbol 值可以显式转为字符串。

      let sym = Symbol('My symbol');
      
      String(sym) // 'Symbol(My symbol)'
      sym.toString() // 'Symbol(My symbol)'
      

      另外,Symbol 值也可以转为布尔值,但是不能转为数值。

      let sym = Symbol();
      Boolean(sym) // true
      !sym  // false
      
      if (sym) {
        // ...
      }
      
      Number(sym) // TypeError
      sym + 2 // TypeError
      

    Symbol.prototype.description

    创建 Symbol 的时候,可以添加一个描述。

    const sym = Symbol('foo');
    

    上面代码中,sym的描述就是字符串foo

    但是,读取这个描述需要将 Symbol 显式转为字符串,即下面的写法。

    const sym = Symbol('foo');
    
    String(sym) // "Symbol(foo)"
    sym.toString() // "Symbol(foo)"
    

    ES2019 提供了一个实例属性description,直接返回 Symbol 的描述。

    const sym = Symbol('foo');
    
    sym.description // "foo"
    

    作为属性名的 Symbol

    由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖

    let mySymbol = Symbol();
    
    // 第一种写法
    let a = {};
    a[mySymbol] = 'Hello!';
    
    // 第二种写法
    let a = {
      [mySymbol]: 'Hello!'
    };
    
    // 第三种写法
    let a = {};
    Object.defineProperty(a, mySymbol, { value: 'Hello!' });
    
    // 以上写法都得到同样结果
    a[mySymbol] // "Hello!"
    

    上面代码通过方括号结构和Object.defineProperty,将对象的属性名指定为一个 Symbol 值。

    注意,Symbol 值作为对象属性名时,不能用点运算符。

    const mySymbol = Symbol();
    const a = {};
    
    a.mySymbol = 'Hello!';
    a[mySymbol] // undefined
    a['mySymbol'] // "Hello!"
    

    上面代码中,因为点运算符后面总是字符串,所以不会读取mySymbol作为标识名所指代的那个值,导致a的属性名实际上是一个字符串,而不是一个 Symbol 值。

    同理,在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。

    let s = Symbol();
    
    let obj = {
      [s]: function (arg) { ... }
    };
    
    obj[s](123);
    

    上面代码中,如果s不放在方括号中,该属性的键名就是字符串s,而不是s所代表的那个 Symbol 值

    采用增强的对象写法,上面代码的obj对象可以写得更简洁一些。

    let obj = {
      [s](arg) { ... }
    };
    

    Symbol 类型还可以用于定义一组常量,保证这组常量的值都是不相等的。

    const log = {};
    
    log.levels = {
      DEBUG: Symbol('debug'),
      INFO: Symbol('info'),
      WARN: Symbol('warn')
    };
    console.log(log.levels.DEBUG, 'debug message');
    console.log(log.levels.INFO, 'info message');
    

    下面是另外一个例子。

    const COLOR_RED    = Symbol();
    const COLOR_GREEN  = Symbol();
    
    function getComplement(color) {
      switch (color) {
        case COLOR_RED:
          return COLOR_GREEN;
        case COLOR_GREEN:
          return COLOR_RED;
        default:
          throw new Error('Undefined color');
        }
    }
    

    常量使用 Symbol 值最大的好处,就是其他任何值都不可能有相同的值了,因此可以保证上面的switch语句会按设计的方式工作。

    还有一点需要注意,Symbol 值作为属性名时,该属性还是公开属性,不是私有属性。

    实例:消除魔术字符串

    题目

    简单介绍一下symbol

    • Symbol是ES6 的新增属性,代表用给定名称作为唯一标识,这种类型的值可以这样创建

      let id=symbol(“id”)
      
    • Symbl确保唯一,即使采用相同的名称,也会产生不同的值,我们创建一个字段,仅为知道对应symbol的人能访问,使用symbol很有用,symbol并不是100%隐藏,有内置方法Object.getOwnPropertySymbols(obj)可以获得所有的symbol。

    • 也有一个方法Reflect.ownKeys(obj)返回对象所有的键,包括symbol。

    • 所以并不是真正隐藏。但大多数库内置方法和语法结构遵循通用约定他们是隐藏的,

    ES6箭头函数的特性

    ES6 增加了箭头函数,基本语法为

    let func = value => value;
    

    相当于

    let func = function (value) {
    	return value;
    };
    

    箭头函数与普通函数的区别在于:

    • 箭头函数没有this,所以需要通过查找作用域链来确定this的值,这就意味着如果箭头函数被非箭头函数包含,this绑定的就是最近一层非箭头函数的this
    • 箭头函数没有自己的arguments对象,但是可以访问外围函数的arguments对象
    • 不能通过new关键字调用,同样也没有new.target值和原型

    简单讲一讲ES6的一些新特性

    • ES6在变量的声明和定义方面增加了let、const声明变量,有局部变量的概念,
    • 赋值中有比较吸引人的结构赋值,
    • 同时ES6对字符串、 数组、正则、对象、函数等拓展了一些方法,如字符串方面的模板字符串、函数方面的默认参数、对象方面属性的简洁表达方式,
    • ES6也 引入了新的数据类型symbol,新的数据结构set和map,symbol可以通过typeof检测出来
    • 为解决异步回调问题,引入了promise和 generator,
    • 还有最为吸引人了实现Class和模块,通过Class可以更好的面向对象编程,使用模块加载方便模块化编程,当然考虑到 浏览器兼容性,我们在实际开发中需要使用babel进行编译

    重要的特性:

    • ES5只有全局作用域和函数作用域,块级作用域的好处是不再需要立即执行的函数表达式,循环体中的闭包不再有问题
    • rest参数:用于获取函数的多余参数,这样就不需要使用arguments对象了,
    • promise:一种异步编程的解决方案,比传统的解决方案回调函数和事件更合理强大
    • 模块化:其模块功能主要有两个命令构成,export和import,export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能

    箭头函数和function有什么区别

    箭头函数根本就没有绑定自己的this,在箭头函数中调用 this 时,仅仅是简单的沿着作用域链向上寻找,找到最近的一个 this 拿来使用

  • 相关阅读:
    查看进程,按内存从大到小 ,查看进程,按CPU利用率从大到小排序
    haproxy 安装 各个参数的测试
    ps -C nginx --no-header |wc -l
    lsof -ntP -i:端口取出 动行程序的PID 然后xargs kill -9 这个进程
    linux 普通用户切换成root免密码
    inter x86 emulator accelerator(HAXM installer) not compatible with windows
    react-native 相关问题
    SQLCE数据工具(Flyhoward Ltd SDF Viewer)
    Android APK反编译就这么简单 详解(附图)
    react.js 教程之 Installation 安装
  • 原文地址:https://www.cnblogs.com/zhoujingguoguo/p/11539609.html
Copyright © 2011-2022 走看看