JS篇: 原型链

原型和原型链(prototype chain)

2021/4/29

  • 通过原型这种机制,JavaScript 中的对象从其他对象继承功能特性;这种继承机制与经典的面向对象编程语言的继承机制不同。

一. 基于原型的语言

  • JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象

  • 对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。

  • 这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

  • 准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非对象实例本身。

建立连接

  • 在传统的面向对象程序设计(Object Oriented Programming,OOP)中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。

  • 在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。

  • 注意:__proto__是每个实例上都有的属性,prototype是构造函数的属性,也就是说

    • Object.getPrototypeOf(new Foobar())===new Foobar().__proto__===Foobar.prototype
      复制代码

二. 查找过程

1. 创建一个实例对象

  • function doSomething(){}
    doSomething.net="ninini";
    doSomething.prototype.foo = "bar"; 
    
    
    var doSomeInstancing = new doSomething();
    doSomeInstancing.prop = "some value";
    复制代码

  • 可见,构造函数的prototype中的constructor指向自己本身,构造函数是继承函数而来的,构造函数的prototype对象是继承对象的

2.沿着原型链往上查找

  • 当你访问 doSomeInstancing 的一个属性, 浏览器首先查找 doSomeInstancing 是否有这个属性
  • 如果 doSomeInstancing 没有这个属性, 然后浏览器就会在 doSomeInstancing__proto__ 中查找这个属性(也就是 doSomething.prototype).
  • 如果 doSomeInstancing 的 __proto__ (也就是 doSomething.prototype)有这个属性, 那么 doSomeInstancing 的 __proto__ 上的这个属性就会被使用.
  • 否则, 浏览器就会去查找 doSomeInstancing 的 __proto____proto__ ,看它是否有这个属性.

3. prototype 属性:继承成员被定义的地方

4. create()

  • var person2 = Object.create(person1);
    复制代码
  • **Object.create()**方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。这里以 person1 为原型对象创建了 person2 对象

5. constructor 属性

  • 每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。

  • 你可以在 constructor 属性的末尾添加一对圆括号(括号中包含所需的参数),从而用这个构造器创建另一个对象实例。毕竟构造器是一个函数,故可以通过圆括号调用;只需在前面添加 new 关键字,便能将此函数作为构造器使用。

  • function Person(name) {
       this.name=name
    }
    let person1=new Person('1')
    var person2 = new person1.constructor('2')
    复制代码

6. 修改原型

  • 你很少看到属性定义在 prototype 属性中,因为如此定义不够灵活。

  • 当想根据实例某些属性值设置原型属性值时

  • Person.prototype.fullName = this.name.first + ' ' + this.name.last;
    // 注意,这样设置是没有效果的,因为这里的this默认指向window
    复制代码
  • Person.prototype.fullName =function(){return this.name.first + ' ' + this.name.last;}
    // 这样设置会让this指向调用原型中该方法的实例对象
    复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享