ES6符号与符号属性

本文详细介绍了JavaScript ES6中的符号类型,包括如何创建和使用符号值,如何实现共享,以及如何转换和检索符号。还探讨了知名的元编程符号,如Symbol.hasInstance、Symbol.isConcatSpreadable等,用于修改内置行为。最后,总结了符号在数据类型转换、对象描述和with语句限制中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

      JavaScript在ES6之前有5种基本类型(number Boolen string null undefined),在 ES6新增了一个基本类型—符号(symbol),本篇文章将会讲解符号的相关内容。

 let firstName = Symbol();
 console.log(typeof firstName); // symbol

创建符号值

      使用Symbol函数可以创建一个符号值,符号值没有字面量形式。

let firstName = Symbol();

注意:new Symbol()将会抛出错误。因为符号值是基本类型的值
      创建符号值还可以添加一个字符串形式的描述的参数。此描述并不能用来访问对应属性,但可以用来调试以及增加代码的可读性。

let lastName = Symbol("123");
var person = {};
person[lastName] = "lucy";
console.log("123" in person) //false

      符号的描述内容可以通过 变量名.description 提取出来

let lastName = Symbol("123");
console.log(lastName.description); //123

使用符号值

      创建的符号值类型的变量可以作为对象中的需计算属性名进行使用。

  let lastName = Symbol("123");
  let person = {
  		[lastName] : "lucy"
  }
  console.log(person[lastName]); //lucy

共享符号值

      在不同的代码段中使用相同的符号值,ES6提供了全局符号注册表。
      什么是全局符号注册表?
它类似于全局作用域,是一个共享环境。
1.Symbol.for()创建共享符号值
      此方法可以添加一个字符串类型的参数,作为目标符号值的唯一标识符,同时作为描述信息。

 let a = Symbol.for("first");
 let obj = {};
 obj[a] = "apple";
 console.log(obj[a]); //apple

      此方法看起来和刚刚的Symbol()没有太多差别,其实是有很大差别的。
      下面看一下它的执行的过程:

      首先搜索全局符号注册表,是否存在键值为“first”的符号值,如果存在,直接返回这个已存在的符号值;如果不存在,会创建一个新的符号值,并将“first”键值记录到全局符号注册表中,返回这个新的符号值。

      意味着使用同一个键值调用symbol.for()方法都会返回同一个符号值,包含同一个符号值可以互换使用。

let a = Symbol.for("first");
let obj = {};
obj[a] = "apple";
console.log(obj[a]); //apple
console.log(a); //Symbol(first)
let a1 = Symbol.for("first");
console.log(a1 === a); //true;
console.log(obj[a1]);//apple

2.Symbol.keyFor() 在全局符号注册表中根据符号值检索出对应的键值。

let person1 = Symbol.for("first");
console.log(Symbol.keyFor(person1)); //first
let person2 = Symbol.for("first");
console.log(Symbol.keyFor(person2)); //first
let person3 = Symbol("first");
console.log(Symbol.keyFor(person3)); //undefined
// 因为person3并不在全局符号注册表中,所以无相关的键值

      使用符号值可以避免名字相同而无法显示。

let user1 = {
     name: "张三",
     key: Symbol("信科院张三")
}
let user2 = {
     name: "张三",
     key: Symbol("张三")
 }
let grade = {
    [user1.key]: {
           math: 20,
            chinese: 100
	},
   [user2.key]: {
           math: 90,
           chinese: 60
	}
}
console.log(grade[user1.key]); //{math: 20, chinese: 100}
console.log(grade[user2.key]); //{math: 90, chinese: 60}

符号值的转换

      无法直接转换为字符串或数值。
      转换成字符串的方法:

let firstName = Symbol.for("first"),
	str = String(firstName);
console.log(typeof str); //string
console.log(str); //Symbol(first)

检索符号值

      ES6新增Object.getOwnPropertySymbols()方法检索(遍历)对象的符号类型属性,返回一个数组,包含对象自有属性名中的符号值。

let symbol1 = Symbol.for("符号1");
let symbol2 = Symbol.for("符号2")
let obj = {
    [symbol1]: "123",
    [symbol2]: "234"
}
let symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols.length); //2
console.log(symbols[0]); //Symbol(符号1)
console.log(obj[symbols[0]]); //123

      所有对象初始情况都不包括自有符号类型的属性,但对象可以从它们的原型上继承符号类型属性。在ES6预定义了一些此类属性—知名符号

使用知名符号暴露内部方法------元编程(不常用)

制定修改规则的方法
元编程:可以对原生js的操作进行修改
一共有11种,本篇文章介绍公用的知名符号(9种),其余将会在对应内容中讲解。

Symbol.hasInstance判断指定对象是否为本函数的一个实例

obj instanceof Array;
//obj 是否是Array的一个实例
//等价于
Array[Symbol.hasInstance](obj);

let instance = {
    
    }
};
console.log({
         a: 1
}
instanceof instance); //TypeError: Right-hand side of 'instanceof' is not callable

      本身并不能被调用,重写了该对象的Symbol.hasInstance使得可以调用,并返回true

let instance = {
    [Symbol.hasInstance](value) {
       return "a in value";
    }
};
console.log({
      a: 1
}
instanceof instance); //true

Symbol.isConcatSpreadable

      属性为布尔类型,它表示目标对象拥有长度属性与数值类型的键、并且数值类型键所对应的属性值在参与concat()调用时需要被分离为个体,让它表现的像数组一样。
concat() 是数组的拼接方式。

let collection = {
       0: "hello",
       1: "world",
       2: "我是程序员",
       length: 3,
       [Symbol.isConcatSpreadable]: true
};
let message = ["hi"].concat(collection);
console.log(message.length); //4
console.log(message); //["hi", "hello", "world", "我是程序员"]

Symbol.match、Symbol.replace、Symbol.search、Symbol.split

      使用这些方法可以创建一个类似正则表达式的对象,以便配合字符串的方法使用。字符串与正则表达式密切相关,字符串拥有几个方法可以接受正则表达式作为参数的方法。

match()判断指定字符串是否与一个正则表达式相匹配
Symbol.match() 此函数接受一个字符串参数。制定匹配规则

 let obj = {
     [Symbol.match](value) {
        return value.length === 4;
      }
}
console.log("a".match(obj)); //false
console.log("abcd".match(obj)); //true

replace()对正则表达式匹配结果进行替换。
Symbol.replace() 此函数接收两个字符串参数。制定替换规则

let hasLength10 = {
    [Symbol.replace](value, replacement) {
        return value.length === 10 ? value.substring(0, 5) + " " + replacement : value;
         // substring(start,stop) 方法用于提取字符串中介于两个指定下标之间的字符。
         // start 必写,stop 可写可不写  提取的是 start到stop-1
     }
};
let message1 = "hello world";
let message2 = "hello john";
let replace1 = message1.replace(hasLength10, "lucy");
// 不等于10 那么执行后者 输出message1.value
let replace2 = message2.replace(hasLength10, "lucy");
// 等于10,那么执行前者  输出message2的索引[0]-[4]的内容并添加空格添加replacemet即lucy
console.log(replace1); //hello world
console.log(replace2); //hello lucy

search() 在字符串内对正则表达式的匹配结果进行定位。
Symbol.search()此函数接受一个字符串参数。判断字符串是否符合制定的规则。

let hasLength10 = {
    [Symbol.search](value) {
        return value.length === 10 ? "true" : "false";
        // 如果value的长度为10   返回 true    否则 返回false
    }
};
let message1 = "hello world";
let message2 = "hello john";
let search1 = message1.search(hasLength10);
let search2 = message2.search(hasLength10);
console.log(search1); //false
console.log(search2); //true

split() 使用正则表达式将字符串分隔为数组
Symbol.split() 此函数接受一个参数。分隔规则的制定

let hasLength10 = {
    [Symbol.split](value) {
        return value.length === 10 ? [
              value[0],
              value[1],
              value[2],
              value[3],
              value[4],
              value[5],
              value[6],
              value[7],
              value[8],
              value[9]
        ] : [value];
        // 如果value的length 为10,返回分隔开的数组,否则原封不变地返回
    }
};
let message1 = "hello world";
let message2 = "hello john";
let split1 = message1.split(hasLength10);
let split2 = message2.split(hasLength10);
console.log(split1); //["hello world"]
console.log(split2); //["h", "e", "l", "l", "o", " ", "j", "o", "h", "n"]

Symbol.toPrimitive 数据类型转换

Symbol.toStringTag创建对象描述信息

Symbol.unscopables 一个对象,该对象的属性指示了哪些属性名不允许被包含在with语句中

结语

      本篇文章介绍了ES6新增的符号方法,重点掌握创建、共享、使用、检索符号值,知名符号的那几种方法不常用,日常几乎用不上,了解即可,有些仅列了出来,有兴趣可以自己查找并深入理解掌握。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值