关于原型链

1-__proto__([[Prototype]])prototype

每个对象都有一个隐式原型,这个隐式原型可以通过

obj.__proto__
Object.getPrototypeOf(obj)

这两种方式获取;
我们都知道对象是通过构造函数构造的,new关键字构造的,
构造函数上有一个显式原型属性,对象的隐式原型就指向了它的构造函数的显式原型。

 let obj1 = new Object()
 console.log(obj1.__proto__ == Object.prototype)//true

而这个构造函数也是一个函数对象对不对?所以构造函数的隐式原型对象也是指向函数的显式原型对象的。

console.log(Object.__proto__ == Function.prototype)

例子:

//Person构造函数
  function Person() {

  }
  //通过构造函数得到两个实例对象
  let p1 = new Person()
  let p2 = new Person()
  console.log(p1.__proto__ == Person.prototype)//true
  //Person也是一个函数对象,是new Function的语法糖
  console.log(Person.__proto__ == Function.prototype)//true

所以,对象上只有隐式原型对象__proto__,而它的构造函数上因为既是函数又是函数对象,所以既有显式原型又有隐式原型对象,一个对象的隐式原型指向它的构造函数的显式原型。

原型对象上的constructor属性

指向当前的构造函数

console.log(p1.__proto__.constructor)
console.log(Person.prototype.constructor)
console.log(Function.prototype.constructor)

在这里插入图片描述

原型链是什么?

每个对象有一个隐式原型对象,用__proto__代替。指向构造函数的显式原型对象,这个隐式原型对象也是一个对象对不对,所以隐式原型对象上也有__proto__隐式原型对象,
所以当我们查找一个对象的key对应的属性值的时候,对象本身没找到,会查找对象的隐式原型,隐式原型的隐式原型对象……这样层层查找的轨迹就是原型链。原型链总有尽头,那尽头是什么呢?就是Object对象的隐式原型对象,而它指向null,所以在代码中我们查找到原型对象的值为null的时候说明查找到了尽头。
我们知道对象可以通过原型链查找属性与方法,那在原型链上重写的方法就会被所有通过原型链继承的对象共享。

2-原型链实现继承

主要原理是让父类的实例对象作为子类构造函数的显式原型对象,这个父类实例对象的隐式原型指向的是自身构造函数的显式原型对象,这个显式原型对象的隐式原型对象指向的Object的原型对象。

  function Person() {

  }
  function Student() {

  }
  let p = new Person()
  Student.prototype = p
  let stu = new Student()
  console.log(stu.__proto__ == Student.prototype)//true
  console.log(Student.prototype == p)//true
  console.log(stu.__proto__ == p)//true
  console.log(p.__proto__ == Person.prototype)//true
  console.log(Person.prototype.__proto__)//Object对象
  console.log(Person.prototype.__proto__.__proto__)//null
  //Object.create方法,使用现有对象作为对象的原型
  let o = Object.create(p)
  console.log(o.__proto__ == p)//true
3-一些相关的方法
instanceof:检测某个构造函数的显式原型prototype是否在某个实例对象的原型链上
isPropertyOf:检测某个对象是否在某个对象的原型链上。
for in:遍历对象及其原型上的属性
hasOwnProperty:是否是对象自身的属性

Object.defineProperty

4-类class

class是构造函数和原型链的语法糖。所以操作一个类实际也就是操作本质上的构造函数。

使用new关键字的时候调用constructor函数的时候做了什么?

//改变隐式原型是为了继承,改变this指向是为了为原型对象挂载属性;
新建一个空对象,这个对象其实就是原型对象;
将这个对象隐式原型对象被赋值为构造函数也就是类的显式原型对象;
将构造函数内部的this指向这个对象;
然后是执行构造函数内的代码,大致就是挂载属性与方法到这个空对象中;
如果构造函数有传入的对象返回那个对象,如果没有其他对象就返回这个空对象。

  class Person {
    constructor(name, age) {
      //使用new关键字实例化类(实例化对象)的时候会自动调用这个函数
      //在这个函数主要做的是在原型对象上绑定共享属性与方法
      this.address = "南京"
      this.sex = "女"
      this.name = name
      this.age = age
    }
    //setter、getter方法
    set name(name) {
      console.log("调用了setter方法")
      this._name = name
    }
    get name() {
      console.log("调用了getter方法")
      return this._name
    }
    getAge() {
      return "年龄是:" + this.age
    }
    //静态方法
    static address() {
      return new Person("syc", 70)
    }
    //extends和super
  }
  let p = new Person("yyy", 20)
  console.log(p.name)//调用了setter和getter方法
  console.log(Person.address())
  class Student extends Person {
    constructor(name, age, classes) {
      //复用父类的构造函数需要super关键字
      super(name, age)
      this.classes = classes
    }
    getMessage() {
      return this.name + ":" + this.address + ":" + this.age + ":" + this.classes
    }
    getAge() {
      //调用父类方法需要用super
      return super.getAge()
    }
    static Ok() {
      //调用父类静态方法用super
      return super.address()
    }
  }
  let stu = new Student("zzz", 12, 1903)
  console.log(stu.getMessage())
  console.log(stu.getAge())
  console.log(Student.Ok())

继承还可以继承内置类比如Array等,对其内置方法进行修改,方便我们使用内置类;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值