# js原型知识小记

TIP

本篇文章作为复习原型知识使用

# proto 和 prototype

  • 首先我们先写一个类来帮助我们理解
class Husky{}
console.dir(Huksy)
1
2
dock
  • 可以看到,这里类中有两个原型,这里我们讲一下区别
  • __proto__原型一般是直接通过Husky来调用的时候使用,只服务于Husky自己
  • prototype原型一般是Husky的实例的原型指向到这里,我们来看一下例子
let twohaha = new Husky()
console.log(twohaha.__proto__ === Husky.prototype)
// true

console.log(twohaha.__proto__ === Husky.__proto__)
// false
1
2
3
4
5
6
  • 这说明我们实例化的对象的__proto__原型指向的是Huskyprototype原型

# 原型链示意图

dock

# Object.create创建没有原型的对象

  • 通过Object.create创建对象husky并在控制台打印,里面没有__proto__
let husky = Object.create(null,{
  name:{
    value:'twohaha'
  }
})
console.log(husky)
// {name: "twohaha"}
//  name: "twohaha"
1
2
3
4
5
6
7
8

# 系统构造函数的原型体现

let arr = []
console.log(arr.__proto__ === Array.prototype)
// true
let str = ''
console.log(str.__proto__ === String.prototype)
// true
let bool = true
console.log(bool.__proto__ === Boolean.prototype)
// true
let obj = {}
console.log(obj.__proto__ === Object.prototype)
// true
let regexp = /^.*/ig
console.log(regexp.__proto__ === RegExp.prototype)
// true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 自定义对象的原型设置

  • 通过Object的方法setPrototypeOf设置原型,getPrototypeOf获取原型
let dog = {tag:'dog'}
let husky = {tag:'details'}
Object.setPrototypeOf(husky,dog)
console.log(Object.getPrototypeOf(husky))
// {tag: "dog"}
1
2
3
4
5
  • 由控制台输出的内容可见,给husky设置原型成功

# 通过实例来创建新实例

  • 因为实例中原型的constructor指向的就是构造函数
function Dog(type){
  this.type = type
}
let husky = new Dog('husky')

function newParentInstance(obj){
  let constructor = Object.getPrototypeOf(obj).constructor
  return new constructor('柯基')
}
console.log(newParentInstance(husky))
// Dog {type: "柯基"}
1
2
3
4
5
6
7
8
9
10
11

# instanceof 检测原型链

  • a instanceof b 可以检测 a的原型链上有没有b
function Dog(){}
function Husky(){}
console.dir(new Dog())
Husky.prototype = new Dog()
console.dir(Husky)
Husky.prototype.constructor = Husky // Husky的constructor在上一步被改变了,这里要改回来
let h = new Husky()
console.log(h instanceof Dog)
1
2
3
4
5
6
7
8

# isPrototypeOf 检测原型链

let dog = {tag:'dog'}
let husky = {tag:'details'}
Object.setPrototypeOf(husky,dog)
console.log(dog.isPrototypeOf(husky))
// true
1
2
3
4
5

# in 和 hasOwnProperty 来获取对象上的属性

  • in 可以检测到原型上的属性
  • getOwnProperty只能获取对象本身的属性
let dog = {tag:'dog'}
let husky = {name:'twohaha'}
Object.setPrototypeOf(husky,dog)
console.log('tag' in husky)
// true
console.log(husky.hasOwnProperty('tag'))
// false
1
2
3
4
5
6
7

# 在构造函数的原型上定义方法

  • 优点共享内存
function Dog(name, type){
  this.name = name
  this.type = type
}

Dog.prototype = {
  constructor: Dog,
  getName(){
    return this.name
  },
  getType(){
    return this.type
  }
}

let husky = new Dog('twohaha','husky')
console.log(husky.getName())
// twohaha
console.log(husky.getType())
// husky
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 原型继承

# 通过prototype.__proto__实现继承

function Dog(name){
  this.name = name
}
Dog.prototype.getType=function(){
  console.log('Is a dog')
}
function Husky(){}
Husky.prototype.__proto__ = Dog.prototype
console.dir(Husky)
let twohaha = new Husky('twohaha')
twohaha.getType()
// Is a dog
1
2
3
4
5
6
7
8
9
10
11
12

# 通过新创建一个一个原型的方式实现继承

function Dog(name){
  this.name = name
}
Dog.prototype.getType=function(){
  console.log('Is a dog')
}
function Husky(){}
Husky.prototype = Object.create(Dog.prototype)
console.dir(Husky)
let twohaha = new Husky('twohaha')
twohaha.getType()
// Is a dog
1
2
3
4
5
6
7
8
9
10
11
12
  • 通过上面的方式实现继承有几个注意点
    • 如果给Husky在原型上定义共享函数,需要在继承逻辑之后写
    • 继承后的原型没有constructor,需要在继承后,重新指定constructor
Husky.prototype = Object.create(Dog.prototype)
Husky.prototype.constructor = Husky
1
2
  • 通过上面的方式constructor是可以被遍历的所以还是不符合,这里我们要改变属性的特征,将enumerable改为false
Husky.prototype = Object.create(Dog.prototype)
Object.defineProperty(Husky.prototype,'constructor',{
  value: Husky,
  enumerable: false // 不可遍历
})
1
2
3
4
5

# 继承使用父类的属性

function Dog(name){
  this.name = name
}
Dog.prototype.showName=function(){
  console.log(this.name)
}
function Husky(name){
  Dog.call(this, name)
}
Husky.prototype.__proto__ = Dog.prototype

let husky = new Husky('twohaha')
husky.showName()
// twohaha
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 封装原型继承工厂

// params{parent} 父类
// params{sub} 子类
function extends(parent,sub){
  sub.prototype = Object.create(parent.prototype)
  Object.defineProperty(sub.prototype,'constructor',{
    value: sub,
    enumerable: false // 不可遍历
  })
}
1
2
3
4
5
6
7
8
9
Last Updated: 1/23/2022, 10:16:22 AM