ES6 Symbol 定义类的属性或者方法

在ES5中,所有的属性名使用的都是标准的字符串,如果你想修改一个别人提供的对象,并且为这个对象增加一个方法的时候,你就要非常小心了,因为你可能选择了一个已经存在的方法的名字。因此在 ES6 中引入了 Symbol 这个类型,当你使用 Symbol 类型来定义类的属性或者方法名的时候,ES6 将保证这个属性和方法名称是全局唯一的。

创建 Symbol 实例

# 第一种方法直接使用Symbol构造函数

var s1 = Symbol();

# 为创建的Symbol对象指定一个名称

var s2 = Symbol("test");

# 使用这种方法,每次创建出来的Symbol对象都是不一样的

var s3 = Symbol("test");

# console.log(s2 == s3)将返回false

# 第二种方法,使用Symbol.for方法来创建Symbol实例

# 使用Symbol.for方法来创建一个Symbol实例的时候,

# 系统首先会在一个全局的注册表中查找是否有相同Key名称的Symbol被创建了,如果找到,就返回已经存在的对象

# 否则,将创建一个全新的对象

s1 = Symbol.for("test")

s2 = Symbol.for("test")

console.log(s1 == s2) //will return true

console.log(s1 == s3) // will return false,因为s3是通过Symbol调用产生的

在我们了解了 ES6 为什么需要引入 Symbol 对象之后,让我们来看一些具体的例子来增加一些对 Symbol 对象的感性的认识。

引用实例1 — 对象的属性

使用 Symbol 来定义类的属性

var a = {};

var s1 = Symbol("test");

a[s1] = "hello world!";

console.log(a[s1]); //this will print "Hello World!"

需要注意的是,当使用Symbol作为属性名的时候,一定要用[]来进行引用,如果你用.(点号)进行引用,那么产生的属性名实际是一个字符串,和Symbol对象本身没一点关系

遍历使用 Symbol 来定义的属性

因为Symbol对象不是一个字符串,所以原先的 Object.getOwnPropertyNames() 方法并不会返回它们,你需要使用专门的Object.getOwnPropertySymbols()方法来访问它们。

var a = {};

var s1 = Symbol("test");

var s2 = Symbol("testfunc");

a[s1] = "hello world!";

a[s2] = function(){

console.log("Test function");

};

//below code will return []

console.log(Object.getOwnPropertyNames(a));

//below code will return [Symbol(test), Symbol(testfunc)]

console.log(Object.getOwnPropertySymbols(a));

引用实例2 — 消除魔术字符串

魔术字符串指的是在代码中反复出现的相同的字符串,对一个结构良好的代码来说,应该尽量消除魔术字符串的存在,而使用常量作为替代。下面就让我们来看一个具体的例子来了解如何使用Symbol来消除代码中的魔术字符串。 在代码中我们尝试根据输入信息的不同返回不同的Hello

# 引入Symbol前的代码

# 在这个代码中es, ch就是魔术字符串

# 当你在调用这个函数的时候,必须确保输入的参数是一个有效的魔术值

function getHello(country){

switch(country){

case "es":

return "Holla";

case "ch":

return "你好";

default:

return "Hello";

}

}

console.log(getHello("es"));

console.log(getHello("ch"));

# 引入Symbol之后的代码

# 在这个代码中es, ch不再是一个具体的字符串

# 因此不管在COUNTRY_CODE中如何修改es, ch的定义,调用方的代码都不需要修改

const COUNTRY_CODE= {

es: Symbol(),

ch: Symbol()

}

function getHello(country){

switch(country){

case COUNTRY_CODE.es:

return "Holla";

case COUNTRY_CODE.ch:

return "你好"

default:

return "Hello"

}

}

console.log(getHello(COUNTRY_CODE.es));

console.log(getHello(COUNTRY_CODE.ch));

ES6 内置的 Symbol 实例

Symbol.hasInstance

对对象使用 instanceof 调用的时候,在 ES6 内部调用的是 obj[Symbol.hasInstance] 方法

Symbol.isConcatSpreadable

决定调用 Array.prototype.contact 方法的时候,对象是否可以展开

var arr1 = [1, 2];

[3, 4].concat(arr1); // return [3, 4, 1, 2]

arr1[Symbol.isConcatSpreadable] = false;

[3, 4].concat(arr1); // return [3, 4, [1, 2]]

和字符串操作相关的 Symbol

  • Symbol.replace 指向一个方法,将被 String.prototype.replace 调用
  • Symbol.search 指向一个方法,将被 String.prototype.search 调用
  • Symbol.split 指向一个方法,将被 String.prototype.split 调用
  • Symbol.match 指向一个方法,将被 str.match(object) 调用
  • Symbol.toStringTag 只想一个方法,将被 Object.prototype.toString 调用

Symbol.iterator

指向对象的默认遍历器

Symbol.toPrimitive

指向一个方法,将对象转换成一个 primitive 类型的值。这个方法将接受一个 hint 参数,表示要转换成哪种primitive类型,具体的value包括”Number”, “String”, “Default”

Symbol.unscopables

指向一个属性,这个属性返回一个 JSON 对象,表示该对象的哪些属性将被 with 环境排除在外,下面是一个具体的例子。

# when Test has no Symbol.unscopables

class Test{

saySomething() { return "abc"; }

}

var saySomething = function() { return "123"; }

with(Test.prototype){

saySomething(); // return "abc"

}

# when Test has Symbole.unscopables

class Test{

saySomething() { return "abc"; }

get [Symbol.unscopables] {

return {saySomething: true};

}

}

with(Test.prototype){

saySomething(); // now return "123"

}

以上是 ES6 Symbol 定义类的属性或者方法 的全部内容, 来源链接: utcz.com/z/264522.html

回到顶部