原型规则

一、5条原型规则: 原型规则是学习原型链的基础

  1. var obj = {}; obj.a = 100;
  2. var arr = []; arr.a = 100;
  3. function fn(){} fn.a = 100;
  4. console.log(obj.__proto__);
  5. console.log(arr.__proto__);
  6. console.log(fn.__proto__);
  7. console.log(fn.prototype);
  8. console.log(obj.__proto__ === Object.prototype)

1、所有的引用类型(数组、对象、函数),都具有对象特性,具有可自由扩展属性(除了”null”外) ,如代码:

  1. var obj = {}; obj.a = 100;
  2. var arr = []; arr.a = 100;
  3. function fn(){} fn.a = 100;

2、所有的引用类型(数组、对象、函数),都有一个proto(隐式原型)属性,构成的属性值也是一个普通的对象,是对象,那么也可以继续自由扩展属性

  1. console.log(obj.__proto__);
  2. console.log(arr.__proto__);
  3. console.log(fn.__proto__);

3、所有的函数,都有一个prototype(显示原型)属性,属性值也是一个普通对象,是对象,那么也可以继续自由扩展属性

  1. console.log(fn.prototype);

4、所有引用类型(数组、对象、函数),proto属性值指向(完全等于) 它的构造函数(大部分为JS的内置函数)的 prototype 属性值

  1. console.log(obj.__proto__ === Object.prototype)

5、当试图得到一个对象(引用类型)的某个属性时,发现这个对象本身没有这个属性,那么会去它的proto(即它的构造函数的prototype)中寻找 new 的 对象 是一个 对象 对象. proto(隐式原型) 是一个对象 构造函数. prototype (显示原型) 是一个对象

设置原型的方法

proto(20210512:已过时,不推荐)

【见】protohttps://www.yuque.com/tqpuuk/yrrefz/bxgqbc

设置原型的现代方法:Object.create,Object.getPrototypeOf,Object.setPrototypeOf

一、设置原型的现代方法有:

例如:

  1. let animal = {
  2. eats: true
  3. };
  4. // 创建一个以 animal 为原型的新对象
  5. let rabbit = Object.create(animal);
  6. alert(rabbit.eats); // true
  7. alert(Object.getPrototypeOf(rabbit) === animal); // true
  8. Object.setPrototypeOf(rabbit, {}); // 将 rabbit 的原型修改为 {}

写入不使用原型

一、原型仅用于读取属性。
二、对于写入/删除操作可以直接在对象上进行。
三、【示例1】我们将为rabbit分配自己的walk:

  1. let animal = {
  2. eats: true,
  3. walk() {
  4. /* rabbit 不会使用此方法 */
  5. }
  6. };
  7. let rabbit = {
  8. __proto__: animal
  9. };
  10. rabbit.walk = function() {
  11. alert("Rabbit! Bounce-bounce!");
  12. };
  13. rabbit.walk(); // Rabbit! Bounce-bounce!

1、从现在开始,rabbit.walk()将立即在对象中找到该方法并执行,而无需使用原型:
image.png
四、访问器(accessor)属性是一个例外,因为分配(assignment)操作是由 setter 函数处理的。因此,写入此类属性实际上与调用函数相同。
1、也就是这个原因,所以下面这段代码中的admin.fullName能够正常运行:

  1. let user = {
  2. name: "John",
  3. surname: "Smith",
  4. set fullName(value) {
  5. [this.name, this.surname] = value.split(" ");
  6. },
  7. get fullName() {
  8. return `${this.name} ${this.surname}`;
  9. }
  10. };
  11. let admin = {
  12. __proto__: user,
  13. isAdmin: true
  14. };
  15. alert(admin.fullName); // John Smith // 属性admin.fullName在原型user中有一个 getter,因此它会被调用
  16. // setter triggers!
  17. admin.fullName = "Alice Cooper"; // 属性在原型中有一个 setter,因此它会被调用
  18. alert(admin.fullName); // Alice Cooper,admin 的内容被修改了
  19. alert(user.fullName); // John Smith,user 的内容被保护了