你不知道的JavaScript(十一):元编程 - 公开符号

Symbol.iterator

var arr = [4, 5, 6, 7, 8, 9];
for (var v of arr) {
    
    
    console.log(v); // 4 5 6 7 8 9 
}

// 定义一个迭代器
arr[Symbol.iterator] = function* () {
    
    
    let i = 0;
    while(true){
    
    
        yield this[i];
        i++;
        if(i >= this.length) break;
    }
};
for (var v of arr) {
    
    
    console.log(v);  // 4 5 6 7 8 9 
}

Symbol.toStringTagSymbol.hasInstance

  • 原型(或实例本身)@@toStringTag 符号指定了在 [object ___] 字符串化时使用的字符串值
  • @@hasInstance 符号是在构造器函数上的一个方法,接受实例对象值,通过返回 truefalse 来指示这个值是否可以被认为是一个实例
function Foo(greeting) {
    
    
    this.greeting = greeting;
}

Foo.prototype[Symbol.toStringTag] = "Foo";

Object.defineProperty(Foo, Symbol.hasInstance, {
    
    
    value: function (inst) {
    
    
        return inst.greeting == "hello";
    }
});

var a = new Foo("hello"),
    b = new Foo("world");

b[Symbol.toStringTag] = "cool";

a.toString();           // '[object Foo]'
String(b);              // '[object cool]'

a instanceof Foo;       // true 
b instanceof Foo;       // false

在这里插入图片描述

在这里插入图片描述

Symbol.species

  • @@species控制要生成新实例时,类的内置方法使用哪一个构造器
class Cool {
    
    
    // 把@@species推迟到子类
    static get [Symbol.species]() {
    
     return this; }
    again() {
    
    
        return new this.constructor[Symbol.species]();
    }
}

class Fun extends Cool {
    
     }

class Awesome extends Cool {
    
    
    // 强制指定@@species为父构造器
    static get [Symbol.species]() {
    
     return Cool; }
}

var a = new Fun(),
    b = new Awesome(),
    c = a.again(),
    d = b.again();

c instanceof Fun;       // true 
d instanceof Awesome;   // false 
d instanceof Cool;      // true

Symbol.toPrimitive

在任意对象值上作为属性的符号 @@toPrimitivesymbol 都可以通过指定一个方法来定制这个 ToPrimitive 强制转换

var arr = [1, 2, 3, 4, 5];
console.log(arr + 10); // 1,2,3,4,510

arr[Symbol.toPrimitive] = function (hint) {
    
    
    if (hint == "default" || hint == "number") {
    
    
        // 求所有数字之和
        return this.reduce(function (acc, curr) {
    
    
            return acc + curr;
        }, 0);
    }
};

console.log(arr + 10); // 25
  • 如果一个对象与另一个非对象值比较,== 运算符调用这个对象上的 ToPrimitive 方法时不指定提示——如果有 @@toPrimitive 方法的话,调用时提示为 "default"。但是,如果比较的两个值都是对象,== 的行为和 === 一样,也就是直接比较其引用

Symbol.isConcatSpreadable

  • 符号 @@isConcatSpreadable 可以被定义为任意对象(比如数组或其他可迭代对象)的布尔型属性(Symbol.isConcatSpreadable),用来指示如果把它传给一个数组的 concat(..) 是否应该将其展开
var a = [1, 2, 3],
    b = [4, 5, 6];

b[Symbol.isConcatSpreadable] = false;

[].concat(a, b); // [1,2,3,[4,5,6]]

Symbol.unscopables

  • 符号 @@unscopables 可以被定义为任意对象的对象属性(Symbol.unscopables),用来指示使用 with 语句时哪些属性可以或不可以暴露为词法变量
var o = {
    
     a: 1, b: 2, c: 3 },
    a = 10, b = 20, c = 30;

o[Symbol.unscopables] = {
    
    
    a: false,
    b: true,
    c: false
};

with (o) {
    
    
    console.log(a, b, c); // 1 20 3 
}

猜你喜欢

转载自blog.csdn.net/weixin_43526371/article/details/127128034