Symbol?面试题中提问的关于Symbol的一些概念?

1.JS的基本数据类型有哪些?(7种)

Number String Boolean Null Object Undefined Symbol

2. Symbol的特点是什么?

表示独一无二的值,Symbol最大的用途是用来定义对象的唯一属性名
比如我们要给一个已有属性的对象添加一个新的属性,新的属性可能和旧的属性名称冲突,这个时候采用Symbol是最好的。

3.如何定义一个Symbol?

通过Symbol()方法可以生成一个symbol,里面可以带参数,也可以不带参数

const symbol1 = Symbol();
const symbol2 = Symbol(42);
const symbol3 = Symbol('foo');

此时如果打印 symbol1, symbol2,symbol3的值 会得出:

console.log(symbol1, symbol2,symbol3) 
>>>Symbol() Symbol(42) Symbol(foo)

4.用typeof返回的数据类型是Symbol

console.log(typeof symbol1);
// expected output: "symbol"

**5.Symbol类型的值是一个独一无二的值

Symbol函数的参数只是表示对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的

console.log(Symbol() === Symbol()); 
// expected output: false 
console.log(Symbol('foo') === Symbol('foo'));
// expected output: false

6.Symbol不是一个构造函数,如果用new Symbol会报错(Symbol是一个原始类型的值,不是对象)。

var symbol = new Symbol(); // 报错:TypeError  

7.由于Symbol值不是对象,所以不能添加属性。

var symbol = Symbol();  
symbol.name = "23"; // 报错:TypeError 

8.Symbol值不能与其他类型的值进行运算。

console.log(Symbol('Alice') + "Bruce"); // 报错  

9.Symbol值可以显式转为字符串,也可以转为布尔值,但是不能转为数值。(强制类型转换)


var symbol = Symbol("Alice");  

//可以通过toString方法转化为字符串
console.log(symbol.toString()); // 输出:Symbol(Alice)
  
//可以通过Boolean方法转化为
console.log(Boolean(symbol)); // 输出:true  
if (symbol)  
    console.log("YES"); // 输出:Yes 
    
//就算是一个空的Symbol返回的也是true
var symbol1 = Symbol();  
console.log(Boolean(symbol1)); // 输出:true  

//不能转化为数字类型的,会报错
console.log(Number(symbol)); // 报错:TypeError  

10.作为对象属性的Symbol

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

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

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

let mySymbol = Symbol();

// 第一种写法
//原来要给一个对象添加字符串属性都是采用对象名.属性名=属性值
//现在要给一个对象添加Symbol类型的属性则是采用方括号形式
let a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
let a = {
  [mySymbol]: 'Hello!'
};

// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果
a[mySymbol] // "Hello!"

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

如果不放在方括号中,该属性名就是字符串,而不是代表的Symbol值。

var name = Symbol();  
var obj1 = {  
  //Symbol类型的属性
    [name]: "Alice"  
};  
var obj2 = {  
  //字符串类型的属性
    name: "Bruce"  
};  
console.log(obj1.name); // 输出:undefined  
console.log(obj1[name]); // 输出:Alice  
console.log(obj2.name); // 输出:Bruce  
console.log(obj2[name]); // 输出:undefined

12.Symbol值作为对象属性名时,不能用点运算符。由于点运算符后面总是字符串,所以不会读取name作为标识名所指代的那个值,导致属性名实际上是一个字符串,而不是一个Symbol值。

var obj = {};  
var name = Symbol();  
obj.name = 'Alice';  
console.log(obj.name);  // "Alice"
console.log(obj[name]);  // undefined 
//注意Symbol属性是不需要加引号的
console.log(obj['name']); // "Alice"

如果改成下面这种形式,会发现在对象中属性名如果一样那么肯定的是,其中一个是Symbol属性,这样同名也不会冲突

var obj = {};  
var name = Symbol();  
obj.name = 'Alice';  
obj[name] = 'Alice';  
console.log(obj.name);  // "Alice"
console.log(obj[name]);  // "Alice"
console.log(obj['name']); // "Alice"

13.作为对象函数名的Symbol

var func = Symbol();  
var obj = {  
    func: function() {  
        console.log("YES");  
    }  
};  
obj.func(); // 输出:YES 

14.获取对象属性的两种方法

(1)Object.getOwnPropertySymbols()方法

	返回只包含Symbol类型的属性名的数组

(2)Object.getOwnPropertyNames()方法

	 返回只包含字符串类型的属性名的数组
var obj = {};  
var age = Symbol("age");  
var job = Symbol("job");
  
//给obj对象添加两个Symbol类型的属性名
obj[age] = "Alice";  
obj[job] = "student";  

//给obj队形添加有一个属性
obj.age = 23;  

//查看obj对象的所有Symbol类型的属性,返回值为数组类型
var symbols = Object.getOwnPropertySymbols(obj);  

//查看obj对象的所有字符串类型的属性,返回值为数组类型
var names = Object.getOwnPropertyNames(obj);  

console.log(symbols.length); // 输出:2  
console.log(symbols); // 输出:Array[Symbol(age), Symbol(job)]  
console.log(obj[symbols[0]]); // 输出:"Alice"

console.log(names); //输出:Array ["age"]
console.log(names.length); // 输出:1  
console.log(obj[names[0]]); // 输出:23  

15.Symbol.for()和Symbol.keyFor()方法

Symbol.for()方法
类似于单例模式(类似一个班只能有一个班主任),首先在全局中搜索有没有以该参数为名称的Symbol值,如果有则返回该Symbol值,否则新建并返回一个以该参数为名称的Symbol值。

//之前没有以该参数为名称的Symbol值,创建一个新的
var symbol1 = Symbol.for('Alice');  
var symbol2 = Symbol.for('Alice');  
console.log(symbol1 === symbol2) // 输出:true 
//之前已经有该参数为名称的Symbol值了
var symbol1 = Symbol("Alice")
var symbol1 = Symbol.for('Alice');  
var symbol2 = Symbol.for('Alice');  
console.log(symbol1 === symbol2) // 输出:true  

Symbol.keyFor()方法

返回一个已创建的Symbol类型值的key,实质是检测该Symbol是否已创建。
Symbol.for()与Symbol()这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。
Symbol.for为 Symbol 值登记的名字,是全局环境的

let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined

16.属性值的遍历

JSON.stringify是在序列化过程中会自动转换成对应的原始值;	
keys 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用[for...in]循环遍历该对象时返回的顺序一致 。
Reflect.ownKeys方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
var obj ={}
obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
    
console.log(JSON.stringify(obj))
// "{"c":"c"}"
console.log(Object.getOwnPropertyNames(obj))
// Array ["c"]
console.log(Object.keys(obj))
// Array ["c"]
console.log(Object.getOwnPropertySymbols(obj))
// [Symbol(a), Symbol(b)]
console.log(Reflect.ownKeys(obj))
//  ["c", Symbol(a), Symbol(b)]

猜你喜欢

转载自blog.csdn.net/canoe777/article/details/107759464