• 深入理解JavaScript中constructor属性
  • 发布于 2个月前
  • 239 热度
    0 评论
什么是constructor
•JavaScript中constructor属性指向创建当前对象的构造函数,该属性是存在原型里的,且是不可靠的 JavaScript中constructor属性
function test() {}
const obj = new test();
console.log(obj.hasOwnProperty('constructor')); // false
console.log(obj.__proto__.hasOwnProperty('constructor')); // true
console.log(obj.__proto__ === test.prototype); // true
console.log(test.prototype.hasOwnProperty('constructor')); // true
/** 堆代码 duidaima.com */
/** constructor是不可靠的 */
function Foo() {}
Foo.prototype = {};
const foo = new Foo();
console.log(foo.constructor === Object);  // true,可以看出不是Foo了
•constructor也是一种用于创建和初始化class[3]创建的对象的特殊方法 Class构造方法[4]

几个典型的constructor:
(async function(){})().constructor === Promise

// 浏览器环境下
this.constructor.constructor === Function
window.constructor.constructor === Function
// 堆代码 duidaima.com
// node环境下
this.constructor.constructor === Function
global.constructor.constructor === Function
JS Proxy getPrototypeOf()
handler.getPrototypeOf()是一个代理方法,当读取代理对象的原型时,该方法就会被调用。语法:

const p = new Proxy(obj, {
  getPrototypeOf(target) { // target 被代理的目标对象。
  ...
  }
});
当 getPrototypeOf 方法被调用时,this 指向的是它所属的处理器对象,getPrototypeOf 方法的返回值必须是一个对象或者 null。在 JavaScript 中,有下面这五种操作(方法/属性/运算符)可以触发 JS 引擎读取一个对象的原型,也就是可以触发 getPrototypeOf() 代理方法的运行:
•Object.getPrototypeOf()
•Reflect.getPrototypeOf()
•proto
•Object.prototype.isPrototypeOf()
•instanceof

如果遇到了下面两种情况,JS 引擎会抛出 TypeError 异常:
•getPrototypeOf() 方法返回的不是对象也不是 null。
•目标对象是不可扩展的,且 getPrototypeOf() 方法返回的原型不是目标对象本身的原型。

基本用法:
const obj = {};
const proto = {};
const handler = {
    getPrototypeOf(target) {
        console.log(target === obj);   // true
        console.log(this === handler); // true
        return proto;
    }
};

var p = new Proxy(obj, handler); // obj是被代理的对象,也就是handler.getPrototypeOf的target参数
console.log(Object.getPrototypeOf(p) === proto);    // true
5 种触发 getPrototypeOf 代理方法的方式:
const obj = {};
const p = new Proxy(obj, {
    getPrototypeOf(target) {
        return Array.prototype;
    }
});

console.log(
    Object.getPrototypeOf(p) === Array.prototype,  // true
    Reflect.getPrototypeOf(p) === Array.prototype, // true
    p.__proto__ === Array.prototype,               // true
    Array.prototype.isPrototypeOf(p),              // true
    p instanceof Array                             // true
);
两种异常的情况:
// getPrototypeOf() 方法返回的不是对象也不是 null
const obj = {};
const p = new Proxy(obj, {
    getPrototypeOf(target) {
        return "foo";
    }
});
Object.getPrototypeOf(p); // TypeError: "foo" is not an object or null

// 目标对象是不可扩展的,且 getPrototypeOf() 方法返回的原型不是目标对象本身的原型
const obj = Object.preventExtensions({}); // obj不可扩展
const p = new Proxy(obj, {
    getPrototypeOf(target) {
        return {};
    }
});
Object.getPrototypeOf(p); // TypeError: expected same prototype value

// 如果对上面的代码做如下的改造就没问题
const obj = Object.preventExtensions({}); // obj不可扩展
const p = new Proxy(obj, {
    getPrototypeOf(target) { // target就是上面的obj
        return obj.__proto__; // 返回的是目标对象本身的原型
    }
});
Object.getPrototypeOf(p); // 不报错

用户评论