JavaScript 基础系列之对象原型

什么是对象原型

JavaScript 中所有的对象都有一个内置属性,称为它的 prototype (原型)。它本身是一个对象,故原型对象也会有它自己的原型,逐渐构成了原型链 。原型链终止于拥有 null 作为其原型的对象上。

准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非对象实例本身。

因此可以看出它的优点: 所有对象实例可以共享它包含的属性和方法

看下面例子

javascript 复制代码
function Person() {}
console.log(Person.prototype) // {constructor: ƒ}
Person.prototype.name = '张三'
Person.prototype.age = 18
Person.prototype.getName = function () {
    console.log('name:' + this.name)
}
var p1 = new Person()
p1.getName() // name:张三
var p2 = new Person()
p2.getName() // name:张三

console.log(p1.getName == p2.getName) // true
console.log(p1.name === p2.name) // true
console.log(Person.prototype.constructor) // ƒ Person() {}
console.log(Person.prototype.constructor.prototype) // {name: "张三", age: 18, getName: ƒ, constructor: ƒ}
console.log(p1.prototype) // undefind
console.log(p1.constructor) // ƒ Person() {}
console.log(p1) // Person {}

由上可得:

Person 有个默认的属性prototype函数可以有属性。每个函数都有一个特殊的属性叫作原型(prototype)

p1和p2访问的都是同一个getName()函数,即他们的属性和方法都是共享的

默认情况下所有的函数都有一个constructor(构造函数)属性 。该属性指向了prototype属性所在函数。如:Person.prototype.constructor 指向的是 Person。

打印 p1:

p1有个__proto__ 属性,该属性内还有:Person的实例、constructor、__proto__。以此提供了一个原型链。

prototype 属性:继承成员被定义的地方

prototype 属性的值是一个对象,我们希望被原型链下游的对象继承的属性和方法,都被储存在其中。

Object.prototype.watch()、``Object.prototype.valueOf() 等等成员,适用于任何继承自 Object() 的对象类型,包括使用构造器创建的新的对象实例。

Object.is()Object.keys(),以及其他不在 prototype 对象内的成员,不会被"对象实例"或"继承自 Object() 的对象类型"所继承。这些方法/属性仅能被 Object() 构造器自身使用

yaml 复制代码
console.log(Person.prototype) // {name: "张三", age: 18, getName: ƒ, constructor: ƒ}
console.log(Object.prototype) //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, ...}

prototype 属性包含(指向)一个对象,你在这个对象中定义需要被继承的属性和方法。

create()

create() 实际做的是从指定原型对象创建一个新的对象。

javascript 复制代码
 function Person(name, age) {
    this.name = name
    this.age = age 
    this.getName = function () {
      console.log('name:' + this.name)
    }
  }
  var p1 = new Person('张三', 18)

  var p3 = Object.create(p1)
  console.log(p3) 
constructor

每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数

arduino 复制代码
// 获得对象实例的构造器的名字
console.log(p1.constructor.name) // Person

修改原型

Person构造器的 prototype 属性添加一个新的方法。

javascript 复制代码
function Person(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
    this.getName = function () {
      console.log('name:' + this.name)
    }
}
var p1 = new Person('张三', 18, '男')

Person.prototype.getSex = function() {
    console.log('sex:' + this.sex);
}
p1.getSex() // sex:男

getSex 方法虽在 p1 实例后定义,但p1也可使用。旧有对象实例的可用功能被自动更新了

这种继承模型下,上游对象的方法不会复制到下游的对象实例中;下游对象本身虽然没有定义这些方法,但浏览器会通过上溯原型链、从上游对象中找到它们。这种继承模型提供了一个强大而可扩展的功能系统。

一种极其常见的对象定义模式是,在构造器(函数体)中定义属性、在 prototype 属性上定义方法。如此,构造器只包含属性定义,而方法则分装在不同的代码块,代码更具可读性。

javascript 复制代码
// 构造器及其属性定义
function Test(a,b,c,d) {
  // 属性定义
};

// 定义第一个方法
Test.prototype.x = function () { ... }

// 定义第二个方法
Test.prototype.y = function () { ... }

继承

例子

javascript 复制代码
function Person(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
    this.getName = function () {
      console.log('name:' + this.name)
    }
}
构造函数继承
csharp 复制代码
var p1 = new Person('张三', 18, 'nan')
p1.getName()
原型式继承

继承的对象函数并不是通过复制而来,而是通过原型链继承(通常被称为 原型式继承 ------ prototypal inheritance)

javascript 复制代码
function Person(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
    this.getName = function () {
      console.log('name:' + this.name)
    }
}

Person.prototype.getSex = function() {
    console.log('sex:' + this.sex);
}

如果一个新的函数要继承上来构造函数的属性和方法,还有增加新的属性和方法:

javascript 复制代码
function Teacher(name, age, sex, profession) {
  Person.call(this, name, age, sex);

  this.profession = profession;
}
var t1 = new Teacher('王二', 30, '男', '老师')
console.log(t1) // Teacher {name: "王二", age: 30, sex: "男", profession: "老师", getName: ƒ}

参考文章:blog.csdn.net/flyingpig20...

相关推荐
KaMeidebaby3 分钟前
卡梅德生物技术快报|适配体筛选技术架构演进:SPARK-seq 高通量平台原理与技术流程解析
大数据·前端·其他·百度·架构·spark·新浪微博
之歆10 分钟前
Day15_JavaScript DOM 事件完全指南:从基础到实战(上)
开发语言·javascript·ecmascript
todaycode10 分钟前
Vue + CPP项目
javascript·c++·vue.js
ZC跨境爬虫14 分钟前
跟着 MDN 学CSS day_7:(层叠优先级与继承)
前端·css·数据库·ui·html
Shadow(⊙o⊙)19 分钟前
qt信号和槽链接的接入与断开
开发语言·前端·c++·qt·学习
慕斯fuafua20 分钟前
JS——DOM操作
前端·javascript·html
忆林52022 分钟前
Jenkins前端打包构建老项目拯救指南
运维·前端·jenkins
GISer_Jing23 分钟前
深入解析 Three.js:从架构设计到 WebGPU 渲染革命
javascript·信息可视化·webgl
微祎_28 分钟前
写给新手的 triton-inference-server-ge-backend:昇腾Triton推理服务后端到底是啥?
前端·人工智能·cann
烂不烂问厨房32 分钟前
两张图片拼接在一起中间有条白线
前端