您的位置:首页 > 其它

原型和原型链

2019-03-28 18:44 183 查看

原型和原型链

一、构造函数
构造函数模式的目的就是为了创建一个自定义类,并且创建这个类的实例。构造函数模式中拥有了类和实例的概念,并且实例和实例之间是相互独立的,即实例识别。
构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。另外就是调用方式的不同,普通函数是直接调用,而构造函数需要使用new关键字来调用。

function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
this.sayName = function () {
alert(this.name);
}
}
var per = new Person("a", 12, "女");
function Dog(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
var dog = new Dog("小花", 4, "雌")
console.log(per)
console.log(dog);

二、原型链
1

.__proto__和constructor

每一个对象数据类型(普通的对象、实例、prototype…)也天生自带一个属性__proto__,属性值是当前实例所属类的原型(prototype)。原型对象中有一个属性constructor, 它指向函数对象。

function Person() {}
var person = new Person()
console.log(person.__proto__ === Person.prototype)//true
console.log(Person.prototype.constructor===Person)//true

//顺便学习一个ES5的方法,可以获得对象的原型

console.log(Object.getPrototypeOf(person) === Person.prototype) // true

2.何为原型链
在JavaScript中万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链。
举例说明:person → Person → Object ,普通人继承人类,人类继承对象类
当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined。
我们可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性;使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true

function Person() {}
Person.prototype.a = 123;
Person.prototype.sayHello = function () {
alert("hello");
};
var person = new Person()
console.log(person.a)//123
console.log(person.hasOwnProperty('a'));//false
console.log('a'in person)//true

person实例中没有a这个属性,从 person 对象中找不到 a 属性就会从 person 的原型也就是 person.proto ,也就是 Person.prototype中查找,很幸运地得到a的值为123。那假如 person.__proto__中也没有该属性,又该如何查找?
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。Object是JS中所有对象数据类型的基类(最顶层的类)在Object.prototype上没有__proto__这个属性。
console.log(Object.prototype.proto === null) // true
三、所有对象的

__proto__
都指向其构造器的prototype

  • 下面再看看所有这些构造器的实例对象的
    __proto__
    指向谁?
  1. 先看看JavaScript引擎内置构造器

    var obj = {name: 'jack'}
    var arr = [1,2,3]
    var reg = /hello/g
    var date = new Date
    var err = new Error('exception')
    
    console.log(obj.__proto__ === Object.prototype) // true
    console.log(arr.__proto__ === Array.prototype)  // true
    console.log(reg.__proto__ === RegExp.prototype) // true
    console.log(date.__proto__ === Date.prototype)  // true
    console.log(err.__proto__ === Error.prototype)  // true
  2. 再看看自定义的构造器,这里定义了一个Person

    js
    function Person(name) {
    this.name = name
    }
    var p = new Person('jack')
    console.log(p.__proto__ === Person.prototype) // true
  3. 每个对象都有一个constructor属性,可以获取它的构造器,因此以下打印结果也是恒等的

    console.log(p.__proto__ === Person.prototype) // true
    console.log(p.__proto__ === p.constructor.prototype) // true
  4. 上面的Person没有给其原型添加属性或方法,这里给其原型添加一个

    getName
    方法

    function Person(name) {
    this.name = name;
    }
    // 修改原型
    Person.prototype.getName = function () {}
    var p = new Person("jack")
    console.log(p.__proto__ === Person.prototype) // true
    console.log(p.__proto__ === p.constructor.prototype) // true

      可以看到

      p.__proto__
      与Person.prototype,p.constructor.prototype都是恒等的,即都指向同一个对象。

    • 如果换一种方式设置原型,结果就有些不同了

      function Person (name) {
      this.name = name
      }
      // 重写原型
      Person.prototype = {
      getName : function () {}
      }
      var p = new Person("jack")
      console.log(p.__proto__ === Person.prototype) // true
      console.log(p.__proto__ === p.constructor.prototype) // false
      理解 : 这里手动修改了
      Person.prototype
      的指向, 并且指向了一个对象字面量
    • 原来的
      Person.prototype
      是由
      new
      关键字创建的 (
      Object.create(Person.prototype)
      )
      Person.prototype
      里面的
      constructor
      属性指向的是 Person
    • 但是自从改了他的指向之后.他的新指向指的是一个对象字面量, 而这个对象字面量是通过new Object()创建的,所以新指向的空间的constructor的值是Object,而不是Person;
  5. 上面代码中用到的

    __proto__
    目前在
    IE6/7/8/9
    中都不支持.
    IE9
    中可以使用
    Object.getPrototypeOf(ES5)
    获取对象的内部原型.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: