本书未发布

原型

未匹配的标注

原型

prototype 和 proto

  • 每个函数都有一个 prototype 属性(即显式原型),他默认指向一个空的 Object 对象,即原型对象,但是,Object 函数除外
  • 在函数创建的时候会添加显式原型属性
  • 在实例化对象的时候,会添加隐式原型
const fn = new Fn()

Fn.prototype instanceof Object // true

Object.prototype instanceof Object // false

Function.prototype instanceof Object // true
  • 而原型对象有一个 constructor 属性,他又指向了函数本身

  • 实例对象的隐式原型的值等于构造函数的显式原型 (或者可以说是,构造函数的 prototype 指向了原型,原型的 constructor指向了构造函数)

  • 但是,Function 除外,function Function() 的显式原型和隐式原型都指向了 Function 原型

  • 所有函数(包含 Function)都是 Function 的实例

    Function.__proto__ === Function.prototype // true

  • Object 的原型对象是原型链的尽头

  • 每个实例对象都有一个 proto 属性(即隐式原型), 这是一个非标准的属性, 建议在开发和调试中使用, 在线上不要使用

  • 如下所示,当 fn 对象在调用 test 方法的时候,会先在自身上找,如果找不到,则会顺着隐式原型去原型上找

function Fun() {
  console.log(123)
}

// Fun 也是 Function 的实例对象,上面的定义,可以看成是 const Fun = new Function()

Fun.prototype.constructor === Fun // true

Fun.prototype.test = function() {
  console.log('test')
}

const fn = new Fun()

fn.__proto__ === Fun.prototype // true

fn.test()

应用

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

// 如果像上面这样写的话,在多次 new Person 的时候,每个对象都有一个相同的 setName 的函数,
// 这样就会浪费内存空间,所以可以尝试把该方法定义到原型上,如下
function Person(name, age) {
  this.name = name
  this.age = age
}

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

原型链

  • 访问一个对象的属性的流程
    1. 会先在自身上找
    2. 如果自身上找不到,再沿着 proto 原型链往上查找
    3. 如果最终没有找到,则返回 undefined
  • 在原型链的查找过程中,一直都是按照隐式原型来查找的,所以原型链也可以成为是隐式原型链
  • 在给对象设置属性的时候,并不会查找原型链,如果当前对象中没有这个属性,那么就直接给这个对象添加上这个属性

函数

  • 所有函数的隐式原型都是一样的
function Fn() {
  this.test1 = function() {
    console.log('test1')
  }
}

Fn.prototype.test2 = function() {
  console.log('test2')
}

const fn = new Fn()

fn.test1()
fn.test2()

fn.toString()

fn.test3   // undefined
fn.test3() // 报错,fn.test3 is not a function

对象

const a = new Object()

继承

原型链继承

  • 构造函数的实例对象自动拥有构造函数原型对象的属性(和方法)
  • 要实现原型链的继承,得让子类型的原型为父类型的一个实例对象
function Supper() {
  this.supperProp = 'supper'
}

Supper.prototype.showSupperProp = function() {
  console.log(this.supperProp)
}

// 子类型
function Sub() {
  this.subProp = 'sub'
}

// 子类型的原型为父类型的实例对象
Sub.prototype = new Supper()
// 让子类型原型的 constructor 指向子类型
Sub.prototype.constructor = Sub

Sub.prototype.showSubProp = function() {
  console.log(this.subProp)
}

var sub = new Sub()
sub.showSupperProp() // 'supper'
sub.showSubProp() // 'sub'

instanceof 和 isPrototype

  • A instanceof B 是用来判断 A 是否是 B 的实例
function Foo(){}

var f1 = new Foo()

f1 instanceof Foo // true

f1 instanceof Object // true

Object instanceof Function // true

Object instanceof Object // true

Function instanceof Function // true

Function instanceof Object // true

function Foo() {}

Object instanceof Foo // false
  • isPrototype() 是用来判断一个对象是否是某个实例的原型对象

hasOwnProperty 和 in

  • hasOwnProperty 是只会在自身对象中查找是否存在该属性
  • in 先会在自身上查找, 如果找不到, 则去原型上查找

constructor

  • constructor 是表示当前的实例到底是由哪个构造函数产生的

面试题

1.

function F() {}

Object.prototype.a = function() {
  console.log('a')
}

Function.prototype.b = function() {
  console.log('b')
}

const f = new F()
f.a() // 'a'
f.b() // 报错
F.a() // 'a'
F.b() // 'b'

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~