原型规则
一、5条原型规则: 原型规则是学习原型链的基础
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn(){} fn.a = 100;
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);
console.log(fn.prototype);
console.log(obj.__proto__ === Object.prototype)
1、所有的引用类型(数组、对象、函数),都具有对象特性,具有可自由扩展属性(除了”null”外) ,如代码:
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn(){} fn.a = 100;
2、所有的引用类型(数组、对象、函数),都有一个proto(隐式原型)属性,构成的属性值也是一个普通的对象,是对象,那么也可以继续自由扩展属性
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);
3、所有的函数,都有一个prototype(显示原型)属性,属性值也是一个普通对象,是对象,那么也可以继续自由扩展属性
console.log(fn.prototype);
4、所有引用类型(数组、对象、函数),proto属性值指向(完全等于) 它的构造函数(大部分为JS的内置函数)的 prototype 属性值
console.log(obj.__proto__ === Object.prototype)
5、当试图得到一个对象(引用类型)的某个属性时,发现这个对象本身没有这个属性,那么会去它的proto(即它的构造函数的prototype)中寻找 new 的 对象 是一个 对象 对象. proto(隐式原型) 是一个对象 构造函数. prototype (显示原型) 是一个对象
设置原型的方法
proto(20210512:已过时,不推荐)
【见】proto:https://www.yuque.com/tqpuuk/yrrefz/bxgqbc
设置原型的现代方法:Object.create,Object.getPrototypeOf,Object.setPrototypeOf
一、设置原型的现代方法有:
- Object.create(proto, [descriptors])—— 利用给定的proto作为[[Prototype]]和可选的属性描述来创建一个空对象。
- Object.getPrototypeOf(obj)—— 返回对象obj的[[Prototype]]。
- Object.setPrototypeOf(obj, proto)—— 将对象obj的[[Prototype]]设置为proto。
例如:
let animal = {
eats: true
};
// 创建一个以 animal 为原型的新对象
let rabbit = Object.create(animal);
alert(rabbit.eats); // true
alert(Object.getPrototypeOf(rabbit) === animal); // true
Object.setPrototypeOf(rabbit, {}); // 将 rabbit 的原型修改为 {}
写入不使用原型
一、原型仅用于读取属性。
二、对于写入/删除操作可以直接在对象上进行。
三、【示例1】我们将为rabbit分配自己的walk:
let animal = {
eats: true,
walk() {
/* rabbit 不会使用此方法 */
}
};
let rabbit = {
__proto__: animal
};
rabbit.walk = function() {
alert("Rabbit! Bounce-bounce!");
};
rabbit.walk(); // Rabbit! Bounce-bounce!
1、从现在开始,rabbit.walk()将立即在对象中找到该方法并执行,而无需使用原型:
四、访问器(accessor)属性是一个例外,因为分配(assignment)操作是由 setter 函数处理的。因此,写入此类属性实际上与调用函数相同。
1、也就是这个原因,所以下面这段代码中的admin.fullName能够正常运行:
let user = {
name: "John",
surname: "Smith",
set fullName(value) {
[this.name, this.surname] = value.split(" ");
},
get fullName() {
return `${this.name} ${this.surname}`;
}
};
let admin = {
__proto__: user,
isAdmin: true
};
alert(admin.fullName); // John Smith // 属性admin.fullName在原型user中有一个 getter,因此它会被调用
// setter triggers!
admin.fullName = "Alice Cooper"; // 属性在原型中有一个 setter,因此它会被调用
alert(admin.fullName); // Alice Cooper,admin 的内容被修改了
alert(user.fullName); // John Smith,user 的内容被保护了