es6 javascript的__proto__ 属性, Object.setPrototypeOf() , Object.getPrototypeOf()

( 1 )__proto__ 属性

__proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。目前,所有浏览器(包括 IE11 )都部署了这个属性。

// es6 的写法
var obj = {
	method: function() { ... }
};
obj.__proto__ = someOtherObj;
// es5 的写法
var obj = Object.create(someOtherObj);
obj.method = function() { ... };
该属性没有写入 ES6 的正文,而是写入了附录,原因是__proto__前后的双下划线,说明它本质上是一个内部属性,而不是一个正式的对外的 API ,只是由于浏览器广泛支持,才被加入了 ES6 。标准明确规定,只有浏览器必须部署这个属性,其他运行环境不一定需要部署,而且新的代码最好认为这个属性是不存在的。因此,无论从语义的角度,还是从兼容性的角度,都不要使用这个属性,而是使用下面的Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作)、Object.create()(生成操作)代替。

在实现上,__proto__调用的是Object.prototype.__proto__,具体实现如下。

Object.defineProperty(Object.prototype, '__proto__', {
	get() {
		let _thisObj = Object(this);
		return Object.getPrototypeOf(_thisObj);
	},
	set(proto) {
		if (this === undefined || this === null) {
			throw new TypeError();
		}
		if (!isObject(this)) {
			return undefined;
		}
		if (!isObject(proto)) {
			return undefined;
		}
		let status = Reflect.setPrototypeOf(this, proto);
		if (!status) {
			throw new TypeError();
		}
	},
});
function isObject(value) {
	return Object(value) === value;
}
如果一个对象本身部署了__proto__属性,则该属性的值就是对象的原型。

Object.getPrototypeOf({ __proto__: null })
// null


( 2 ) Object.setPrototypeOf()

Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象。它是 ES6 正式推荐的设置原型对象的方法。

//  格式
Object.setPrototypeOf(object, prototype)
//  用法
var o = Object.setPrototypeOf({}, null);
//该方法等同于下面的函数。
function (obj, proto) {
	obj.__proto__ = proto;
	return obj;
}
//下面是一个例子。
let proto = {};
let obj = { x: 10 };
Object.setPrototypeOf(obj, proto);
proto.y = 20;
proto.z = 40;
obj.x // 10
obj.y // 20
obj.z // 40
上面代码将 proto 对象设为 obj 对象的原型,所以从 obj 对象可以读取 proto 对象的属性。

( 3 ) Object.getPrototypeOf()

该方法与 setPrototypeOf 方法配套,用于读取一个对象的 prototype 对象。

Object.getPrototypeOf(obj);
//下面是一个例子。
function Rectangle() {
}
var rec = new Rectangle();
Object.getPrototypeOf(rec) === Rectangle.prototype
// true
Object.setPrototypeOf(rec, Object.prototype);
Object.getPrototypeOf(rec) === Rectangle.prototype
// false







### JavaScript 中 `Object.create` 和 `Object.getPrototypeOf` 的用法及区别 #### 一、`Object.create` 的功能与用途 `Object.create(proto[, propertiesObject])` 是用于创建新对象的方法,其第一个参数指定了新对象的原型对象。通过这种方式,可以显式地控制新建对象的原型链。 - **主要作用** 它允许开发者手动构建具有特定原型的对象实例。例如,当需要基于某个现有对象来定义新的行为时,这种方法非常有用[^1]。 - **语法示例** ```javascript const prototypeObj = { greet: function () { return 'Hello!'; } }; const obj = Object.create(prototypeObj); console.log(obj.greet()); // 输出 Hello! ``` 此方法还可以接受第二个可选参数,用来描述额外属性的行为(如配置 getter 或 setter)。如果仅需简单继承而不涉及复杂初始化逻辑,则推荐使用该方式代替传统的构造函数模式[^4]。 --- #### 二、`Object.getPrototypeOf` 的功能与用途 `Object.getPrototypeOf(object)` 返回指定对象的原型 (即内部 [[Prototype]] 属性),它通常被用来查询某对象的实际父级原型是什么。 - **实际应用案例** - 验证给定值是否属于某种内置类型; - 动态调整某些类库中的默认行为; 以下是具体例子展示如何利用这一特性判断字符串类型的原始形式: ```javascript console.log(Object.getPrototypeOf('foo') === String.prototype); // true console.log(Object.getPrototypeOf(true) === Boolean.prototype); // true ``` 上述代码片段展示了对于基本数据类型封装后的访问机制[^2]。 --- #### 三、两者的对比分析 | 特性 | `Object.create()` | `Object.getPrototypeOf()` | |--------------------------|-------------------------------------------|---------------------------------------| | 主要目的 | 创建一个新的对象并设定它的原型 | 获取已有对象的原型 | | 参数数量 | 至少一个 | 只有一个 | | 是否改变原对象结构 | 不会 | 不会 | | 常见应用场景 | 实现简单的单继承或者多层嵌套关系模拟 | 调试程序期间探索复杂的对象图谱 | 值得注意的是,在 ES6 引入 class 关键字之后,虽然可以通过 extends 来简化许多操作流程,但在更底层的操作层面理解这些基础概念仍然非常重要[^3]^。 另外需要注意的一点是关于性能考量方面:频繁调用此类元编程相关的 API 可能会对运行效率造成一定影响;因此除非必要情况下不建议过度依赖它们来进行日常开发工作. --- ### 总结 综上所述,尽管两者都围绕着 JavaScript 的原型系统展开讨论,但各自侧重点完全不同——前者侧重于生产阶段的新实体制造过程管理,后者则更多关注既有资源的信息挖掘能力提升之上。掌握好这两者之间的界限有助于我们更好地运用面向对象的思想去解决问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值