image.png

原型

__proto__保存的「原型」指向function.prototype

  1. function Car() {}
  2. var car = new Car();
  3. console.log(Car.prototype);
  4. console.log(car);

image.png

结合上面的图我们能看到car.__protot__的原型是Car.prototypeCar.prototype.__proto__的原型是Object.prototype
所以:所有的对象都有自己的原型,包括原型本身!
原型与原型链深入、对象继承、call/apply - 图4

原型链

其实上面👆 的情况就是「原型链」。
「原型链」就是去「原型对象」里一层一层寻找相应的属性的这样的继承属性链就是「原型链」(没有的属性先到我自己的实例上寻找,实例上找不到就去原型对象上寻找,如果原型对象上也没有就继续到原型对象的原型对象去寻找)。

  1. function Professor() {}
  2. Professor.prototype.tSkill = "JAVA";
  3. var professor = new Professor();
  4. function Teacher() {
  5. this.mSkill = "JS/JQ";
  6. }
  7. Teacher.prototype = professor;
  8. var teacher = new Teacher();
  9. function Student() {
  10. this.pSkill = "HTML/CSS";
  11. }
  12. Student.prototype = teacher;
  13. var student = new Student();
  14. console.log(student);
  15. console.log(student.mSkill);
  16. console.log(student.tSkill);

image.png
student实例对象是完全可以访问到mSkilltSkill的,他会沿着原型链条一直寻找,直到顶端。

原型链的顶端

原型链的顶端是Object.prototype

  1. function Professor(){}
  2. console.log(Professor.prototype);

image.png

原型的原型是由系统自带的构造函数function Object(){}构造出来的。
image.png

实例对象操作原型链上的属性

  1. function Professor() {}
  2. Professor.prototype.tSkill = "JAVA";
  3. var professor = new Professor();
  4. function Teacher() {
  5. this.mSkill = "JS/JQ";
  6. this.students = 500;
  7. this.success = {
  8. alibaba: 28,
  9. tencent: 30,
  10. };
  11. }
  12. Teacher.prototype = professor;
  13. var teacher = new Teacher();
  14. function Student() {
  15. this.pSkill = "HTML/CSS";
  16. }
  17. Student.prototype = teacher;
  18. var student = new Student();

现在先尝试去修改Teacher下的success对象

  1. student.success.baidu = 100;
  2. console.log(student, teacher);

image.png
现在我们能看到student实例对象是完全可以更改原型链上引用数据的。

那我们再来看更改一下原始数据:

  1. student.students++;
  2. console.log(student, teacher);
  3. // 当执行到 student.students++ 时,
  4. // 实例对象发现自己没有 students 属性就会到原型上找
  5. // 然后就会执行 this.student = teacher.students++

image.png
我们可以看到当用实例对象student去更改原型上的原始数据,students属性却新增到实例对象本身上!!!

由此总结:

  • 实例对象更改原型链上的「引用数值」会更改原型链上的属性
  • 实例对象更改原型链上的「原始数值」会新增到自己的实例上

this 指向

当构造函数和构造函数原型上有相同的属性时,谁使用this访问,this就指向谁!!!

  1. function Car() {
  2. this.brand = "Benz";
  3. }
  4. Car.prototype = {
  5. brand: "Mazsa",
  6. intor: function () {
  7. console.log("我是" + this.brand + "车");
  8. },
  9. };
  10. var car = new Car();
  11. // car 实例对象访问 intor() 函数
  12. car.intor(); // 我是Benz车
  13. // prototype 访问 intor() 函数
  14. car.prototype.intor(); // 我是Mazsa车

Object.create()

:::info Object构造函数静态方法。 ::: 实例化对象的另外一种写法就是使用Object.create()方法,该方法接受一个对象或者null做为参数。

  1. function Obj() {}
  2. Obj.prototype.num = 1;
  3. // 两种方法构建出的对象一模一样
  4. var obj1 = Object.create(Obj.prototype);
  5. var obj2 = new Obj();
  6. console.log(obj1);
  7. console.log(obj2);

image.png
从外面来看使用newObject.create()创建出来的对象没有任何的区别。

**Object.create()**的好处只是可以给一个对象自定义原型。

指定原型是一个对象:

  1. var test = {
  2. num: 2,
  3. };
  4. var obj3 = Object.create(test);
  5. console.log(obj3);

image.png

指定原型是null

  1. var obj1 = Object.create(null);
  2. console.log(obj1);
  3. obj1.num = 1;
  4. var obj2 = Object.create(obj1);
  5. console.log(obj2);
  6. console.log(obj2.num);

image.png

当一个对象的原型被指定为**null**的时候,该对象无法调用任何的方法。

  1. var obj = Object.create(null);
  2. obj.num = 1;
  3. obj.toString(); // error,not a function

这是因为**obj**被创建的时候原型指定为**null**,所以**obj**就没有原型,所以**obj**是无法根据原型链的规则往上寻找到**Object.prototype**的,因此也就无法使用任何的方法。

还因为obj没有原型,所以给它赋值obj.__proto__是无法使用的。

  1. var obj = Object.create(null);
  2. var obj1 = { count: 1 };
  3. obj.__proto__ = obj1; // 这里的赋值相当于赋值了一个普通的属性
  4. console.log(obj.count); // 所以无法直接访问 count

new 的过程

  • 创建this对象
  • this对象保存构造函数的prototype
  • this对象初始化属性和方法
  • 返回this对象

包装类的方法

  1. var num = new Number(1);
  2. console.log(num.toString()); // "1"
  3. var bool = new Boolean("true");
  4. console.log(bool.toString())

因为包装类也是实例化对象,实例化对象是可以访问到prototype的,所以包装类是完全可以调用自身的方法!!!

undefindnull是无法通过包装类进行包装的,所以它两也就无法调用方法!!!

  1. console.log(undefined.toString()); // error
  2. console.log(null.toString()); // error