SOURCE

// 返回一个新范围对象
function range(from, to) {
    // 继承对象为range函数的methods属性
    let r = Object.create(range.methods);
    // 定义起点和终点
    r.from = from;
    r.to = to;
    return r;
}
// 所有范围对象继承的方法
range.methods = {
    // 适用于文本,日期和数字
    includes(x) { return this.from <= x && x <= this.to; },
    // 该生成器函数使得实例可以迭代
    *[Symbol.iterator]() {
        for (let x = Math.ceil(this.from); x <= this.to; x++) yield x;
    },
    // 返回字符串表示
    toString() {
        return '(' + this.from + '...' + this.to + ')'
    }
}

// 
let r=range(1,3);
console.log('includs:',r.includes(2));
console.log('toString:',r.toString());
console.log('---',[...r]) // 通过迭代器转换为数组

// 如果new.target是undefined,那么包含函数就是作为普通函数
// 被调用的,没有使用new关键字。

// 在构造函数中模拟该特性
function C(){
    if(!new.target) return new C();
    // 这里是初始化代码
}
// 这个技术只适用于以这种老方式定义的构造函数。使用class关
// 键字创建的类不允许不使用new调用它们的构造函数

// 如果不想以构造函数作为媒介,直接测试某个对象原型链中是
// 否包含指定原型,可以使用isPrototypeOf()方法。
console.log('print:',range.methods.isPrototypeOf(r));
console 命令行工具 X clear

                    
>
console