JS原型及继承

50 阅读2分钟

JS创建对象的几种方法

-- 概念
__proto__ 是一个指针,指向他的父对象。

prototype 不是指针,是一个对象。

constructor 是 指向该对象的构造函数。
概念就不说了,网上有很多博客,很容易搜到。
链接:https://blog.csdn.net/HeroIsUseless/article/details/122813603

---- 创建出来的对象都有一个基类,Object。

### 1. Object.create()
let foo = Object.create({})
  因为用{}作为创建的原型,有2层prototype
  foo.__proto__.proto__  === Object.prototype // true
  foo.__proto__ === {} // 一层
  {}.__proto__ === Object.prototype // 第二层
  {}是foo的原型
  
let foo2 = Object.create(p)
  foo2.__proto__  === p 
  p是foo2的原型
  p不一定是对象,也可以是数组。。。。,需要定义。

1661658642313.png

### 2. var a = {}
这个有1prototype
a.__proto__  === Object.prototype // true

puton.png

可以看到,对象里有prototype这个属性,但不能用 . 来访问,用. 来访问会undefined。函数可以访问到。 prototype这个属性是个对象,里面的属性从原型上来,可以推断这个属性的作用是用来做共享的。

let f = Object.create({})
  console.log(f.prototype)// undefined
这里只创建了 f 这个对象,没有给他任何的属性和方法。
  f.toString() // '[object Object]'
  使用toStirng()这个方法,不仅不报错还执行了。
  f 没有就去他的原型上找,看看有没有这个方法,有就执行,没有就报错。
--验证--
let c = Object.create(null)
console.log(c) // No properties
c.toString() // Uncaught TypeError: c.toString is not a function

再来看看最后一种创建方法

### 3. new 关键字
function Person(name) {
   this.name = name
}
let p = new Person('hihi')
就两段代码, 废话一下:Person是构造函数。

------- start 来看 Person.prototype(构造函数的原型)的结构  -------------
Person.prototype {
   constructor: {
     constructor:  Person(name)
     [[Prototype]]: Object
   }
}
--------- end -----
1.new出来一个对象,新对象的原型链指向 构造函数的原型
  p.__proto__ === Person.prototype // true
2. constructor 指向自己
  Person.prototype.constructor === Person // true
3. p没有constructor, 会往上找(原型),p的构造函数是Person
  p.constructor === Person //true

new关键字干了什么
-- 传一个对象
-- 对象原型链指向 function 的 prototyoe
-- 对象执行这个构造函数

继承

实现继承分两步

  • 使用构造函数和原型函数
  • 让对象原型链指向父类

原型继承(古老的)

function Parent(name) {
  this.name = name
}
Parent.prototype.getName = function () {
  console.log(this.name)
}
function Child() {}

如果想要Child 也有 Parent原型上的getName方法,可以这么做。
Child.prototype = new Parent()
// Child.prototype.__proto__ ===  Parent.prototype
Child.prototype.constructor = Child
有些问题:
- 创建Child时,不能传参数
- 如果有属性是引用的属性,一个实例修改了,其他的都会被修。

构造函数继承(古老的)

function Parent(action,name) {
  this.action = action
   this.name = name
}

function Child(id) {
  Parent.apply(this, Array.prototype.slice.call(argument,1))
  this.id = id
}
有些问题:
- 属性和方法如果想继承,只能在构造函数中定义
- 在构造函数中定义了,每次都会创建

组合式继承

省略

总结

创建对象 
// 第1,2种用对象创建对象,第三种是函数创建对象
。。。。
理解上面的内容,可以去看继承了。