JavaScript -- 原型与原型链

简介: JavaScript -- 原型与原型链

根据视频进行整理

【https://www.bilibili.com/video/BV14s411E7qf?p=15】

视频对应资源(百度网盘):

链接:【https://pan.baidu.com/s/1q9LnJcRt5alTV67gUDqpnw】

提取码:1234

1 原型与原型链

1.1 原型 prototype

1、每个函数都有一个prototype属性

// 每个函数都有一个prototype属性
    function myfunc() {
    }
    console.log(myfunc.prototype)
    console.log(Date.prototype)

2、函数的prototype属性,其类型为object

// 每个函数都有一个prototype属性
    function myfunc() {
    }
    console.log( typeof myfunc.prototype)
    console.log( typeof Date.prototype)

3、函数的prototype属性默认指向一个Object空对象(即称为: 原型对象)

Object空对象:

是指该对象上没有我们自定义的属性

console.dir( myfunc.prototype)
    console.log(new Object())

4、函数的prototype属性指向的对象为原型对象

5、原型对象中有一个属性constructor, 它指向函数对象

console.log(myfunc.prototype.constructor === myfunc)
    console.log(Date.prototype.constructor === Date)

6、可以通过prototype给原型对象添加属性(一般是方法)

作用:

可以使函数的所有实例对象都自动拥有原型中的属性(方法)

通过prototype给原型对象添加属性,添加的属性供实例对象使用

// 构造函数
      function Fun() {}
      // 向函数的原型对象上添加属性
      Fun.prototype.test = function() {
        console.log('Fun.prototype.test')
      }
      // 实例化对象
      const fun1 = new Fun()
      console.log(fun1)
      fun1.test()

1.2 显示原型与隐式原型

1、每个函数function都有一个prototype,即显式原型(属性)

2、每个实例对象都有一个__proto__,可称为隐式原型(属性)

// 每个函数function都有一个prototype,即显式原型(属性)
    function Fun() {}
    console.log(Fun.prototype)
    // 每个实例对象都有一个__proto__,可称为隐式原型(属性)
    var fun = new Fun()
    console.log(fun.__proto__)

3、实例化出来的对象的隐式原型的值为其对应构造函数的显式原型的值

显示原型属性指向一个没有我们自定义属性的对象,隐式原型属性指向显示原型属性指向的对象。

// 实例化出来的对象的隐式原型的值为其对应构造函数的显式原型的值
    console.log(fun.__proto__ === Fun.prototype)

// 通过函数的prototype给原型添加属性
    Fun.prototype.test = function() {
      console.log('test')
    }
    // 实例对象调用添加的属性
    fun.test()

函数向原型中添加属性通过显示原型属性

实例对象使用新添加的属性通过隐式原型属性进行查找

输出结果:

小结

  • 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个没有自定义属性的Object对象
  • 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值
  • 程序员能直接操作显式原型, 但不要直接操作隐式原型(ES6之前)

1.3 原型链

function Fn() {
        this.test1 = function () {
          console.log('test1()')
        }
      }
      Fn.prototype.test2 = function () {
        console.log('test2()')
      }
      var fn = new Fn()
      fn.test1()
      fn.test2()
      console.log(fn.toString())
      fn.test3()

访问一个对象的属性时:

  • 先在自身属性中查找,找到返回
  • 如果没有, 再沿着__proto__这条链向上查找, 找到返回
  • 如果最终没找到, 返回undefined

原型链的尽头为Object的原型对象。

原型链:

  • 本质上是隐式原型链
  • 作用: 查找对象的属性(方法)

fn.test3() 会在对象的属性和其原型链中查找

test3() 函数变量,会在作用域链中进行查找

所有函数的隐式原型都相等,因为所有函数都是函数构造器函数Function()的实例对象,所以所有函数对象的隐式原型属性都相等,都等于函数构造器函数Function()的显示原型属性

补充:

1、函数的显示原型指向的对象默认是空Object实例对象(但Object函数的原型对象不满足)

空:对于程序员来说,没有放任何的属性方法到对象中

Object的显示原型对象为null

Object函数:对象的构造函数 Object()

console.log(Fn.prototype instanceof Object) // true
      // Object的显示原型对象再向上就没了
      console.log(Object.prototype instanceof Object) // false
      console.log(Function.prototype instanceof Object) // true

2.、所有函数都是Function的实例(包含Function)

// 自身的实例,隐式原型的指向和现实原型的指向相等
      console.log(Function.__proto__ === Function.prototype)

3、Object的原型对象是原型链尽头

console.log(Object.prototype.__proto__) // null

1.4 原型链_属性问题

1、读取对象的属性值时: 会自动到原型链中查找

2、设置对象的属性值时: 不会查找原型链, 如果当前对象中没有此属性, 直接添加此属性并设置其值

function Fn() {}
      // 在原型上设置一个属性 a 值为 xxx
      Fn.prototype.a = 'xxx'
      // Fn实例化对象 fn1
      var fn1 = new Fn()
      console.log(fn1.a, fn1)
      // Fn实例化对象 fn2
      var fn2 = new Fn()
      // 给 fn2 对象设置属性 a 值为 yyy
      // fn2 中没有 a 属性,会给 fn2 添加一个 a 属性
      fn2.a = 'yyy'
      console.log(fn1.a, fn2.a, fn2)

3、方法一般定义在原型中, 属性一般通过构造函数定义在对象本身上

对象的属性一般在构造函数中进行设置

function Person(name, age) {
    this.name = name
    this.age = age
  }
  Person.prototype.setName = function (name) {
    this.name = name
  }

属性在自身身上(每个对象的属性值会有所不同),方法在原型上

var p1 = new Person('Tom', 12)
  p1.setName('Bob')
  console.log(p1)
  var p2 = new Person('Jack', 12)
  p2.setName('Cat')
  console.log(p2)

1.5 instanceof

instanceof是如何判断的?

表达式: A instanceof B

如果B函数的显式原型对象在A对象的原型链上, 返回true, 否则返回false

// Object这里为构造器函数,是Function的一个实例对象
  // Object => Object.__proto__ === Function.prototype
  console.log(Object instanceof Function) // true
  // Object作为对象的显示原型属性为Object.prototype
  // Object作为构造函数是Function的实例对象,Function是Object的实例(函数是特殊的对象)
  // Object => Object.__proto__ === Function.prototype => Object
  console.log(Object instanceof Object) // true
  console.log(Function instanceof Function) // true
  // 函数是特殊的对象
  console.log(Function instanceof Object) // true
  function Foo() {}
  // 函数类型的数据对象
  // Foo.prototype
  // Object.__proto__ => Function.prototype => Object.prototype 
  console.log(Object instanceof  Foo) // false

1.6 面试题

function A () {
  }
  A.prototype.n = 1
  var b = new A()
  A.prototype = {
    n: 2,
    m: 3
  }
  var c = new A()
  console.log(b.n, b.m, c.n, c.m)

function F (){}
  Object.prototype.a = function(){
    console.log('a()')
  }
  Function.prototype.b = function(){
    console.log('b()')
  }
  var f = new F()
  // f是一个对象
  // f => Object => Object.prototype
  // F是一个函数,Function的实例
  // F => Function => Object => Object.prototype
  f.a()
  // f.b() // 不存在,会报错
  F.a()
  F.b()
  // console.log(f)
  // console.log(Object.prototype)
  // console.log(Function.prototype)


相关文章
|
3月前
|
JavaScript 前端开发 开发者
理解JavaScript中的原型链:基础与实践
【10月更文挑战第8天】理解JavaScript中的原型链:基础与实践
|
2月前
|
JavaScript 前端开发
JavaScript 原型链的实现原理是什么?
JavaScript 原型链的实现原理是通过构造函数的`prototype`属性、对象的`__proto__`属性以及属性查找机制等相互配合,构建了一个从对象到`Object.prototype`的链式结构,实现了对象之间的继承、属性共享和动态扩展等功能,为 JavaScript 的面向对象编程提供了强大的支持。
|
2月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
41 1
JavaScript中的原型 保姆级文章一文搞懂
|
5月前
|
JavaScript 前端开发
如何在JavaScript中实现基于原型的继承机制
【8月更文挑战第14天】如何在JavaScript中实现基于原型的继承机制
36 0
|
2月前
|
JavaScript 前端开发
原型链在 JavaScript 中的作用是什么?
原型链是 JavaScript 中实现面向对象编程的重要机制之一,它为代码的组织、复用、扩展和多态性提供了强大的支持,使得 JavaScript 能够以简洁而灵活的方式构建复杂的应用程序。深入理解和熟练运用原型链,对于提升 JavaScript 编程能力和开发高质量的应用具有重要意义。
|
2月前
|
JavaScript 前端开发
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
|
3月前
|
JavaScript 前端开发 开发者
探索JavaScript原型链:深入理解与实战应用
【10月更文挑战第21天】探索JavaScript原型链:深入理解与实战应用
46 1
|
3月前
|
JavaScript 前端开发 开发者
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
55 0
|
3月前
|
JavaScript 前端开发 开发者
原型链深入解析:JavaScript中的核心机制
【10月更文挑战第13天】原型链深入解析:JavaScript中的核心机制
45 0
|
3月前
|
JavaScript 前端开发 安全
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
37 0