javascript 原型

122 阅读2分钟

在前端开发的工作中,JavaScript的原型链到处可见,它主要是为了解决继承的问题,因为js本身就是一门面向对象的语言,而继承是面向对象编程的三要素之一,那么如何来理解并实现js中的继承呢。

构造函数

JavaScript中,通过构造函数来实现对象的继承,最明显的就是,构建一个对象

let obj = new Object();

Object本身就是一个构造函数,通过模板化的形式,来生成一个个对象实例,现在我们新建一个构造函数

function Cat就是构造函数,cat就是它生产出来的实例,说了这些,跟原型有什么关系呢?

function Cat(){
  this.age = 3;
}
let cat = new Cat();
console.log(cat.age) // 3

Cat就是构造函数,cat就是它生产出来的实例,说了这些,跟原型有什么关系呢?

每个函数都有一个prototype,它本身是一个对象,指向函数的原型,如图为打印结果

可以看到Cat.prototype的值,包含了构造函数 constructor__proto__

__proto__是什么

每个对象实例都有 __proto__,指向实例对象的原型,这个由运行环境来提供

function Cat() {
    this.color = 'orange'
}

var cat = new Cat()
console.log(cat.__proto__)
console.log(Cat.prototype === cat.__proto__)  // true

具体可以参考下图:

细心的你应该已经发现了,上图的右边有一条线还没有结束,这个是指什么呢?

继承

我们先写一段代码

function Cat(){
	this.age = 3;
}

Cat.prototype.name = 'mi';
let cat = new Cat();
cat; // Cat {age: 3}
cat.name // "mi"
console.log(cat.hasOwnProperty('age')) // true
console.log(cat.hasOwnProperty('name')) // false

可以看到,虽然cat实例有name属性并且可以访问,但是name属性并不属于它本身,而是继承自 Cat, cat实例本身没有这个属性值,可以通过原型链来逐级访问,这就是所谓的继承。当访问对象的某一属性无法访问到,就会逐级去访问原型链(通过 __proto__,如: Cat.prototype.__ptoto__ , cat.__proto__.__proto__ ),来获取到这个值,直到原型链返回null,为什么会返回null呢?

对象的构造函数为 Object,那我们来看下它的原型是什么?

Object.prototype.__proto__ // null

所以 Object.prototype就是传说中的最高级了,位于原型链的最顶端。下面奉上完整的图片: