前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript难点:原型、原型链、继承、new、prototype和constructor

JavaScript难点:原型、原型链、继承、new、prototype和constructor

作者头像
cafehaus
发布2023-12-21 16:39:05
1250
发布2023-12-21 16:39:05
举报
文章被收录于专栏:大前端全栈开发

原型

原型(prototype)是 JavaScript 中对象的一个特殊属性,它用于实现属性和方法的继承。

实例对象的原型属性可以用 __proto__ 访问到,推荐用 Object.getPrototypeOf() 去获取。

原型链

任何一个实例,通过原型链,都能找到它上面的原型,该原型对象中的方法和属性,可以被所有的原型实例共享,原型对象中依然有它自身的原型,当我们访问一个实例属性或方法时,如果自身没有,就会一级一级地去原型对象上找,这样就构成一个原型链。

继承

JavaScript 不像 Java、C++ 这种纯面向对象的语言,可以通过类实现继承,JavaScript中的继承是通过原型实现的,即使 ES6 中新增的 class 类也只是原型的语法糖而已。

new

构造函数只能通过 new 关键字才能调用创建实例,class 类必须要加 new 否则会报错。当我们 new 的时候实际会调用内部的 constructor 构造函数,会做以下4步:

  • 新建一个对象
  • 将对象的原型指向构造函数的 prototype
  • 绑定 this,执行构造函数中的代码
  • 返回对象

prototype

JavaScript 规定,每一个构造函数都有一个 prototype 属性(其实普通函数也有的,构造函数本身就是一个普通函数),指向另一个对象。注意这个 prototype 就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有,注意实例是没有 prototype 属性。

  • prototype:显示原型,函数才有的
  • __proto__:隐式原型,实例对象才有的,在浏览器中可以通过这个访问对象的原型,不过 Mozilla 推荐使用 Object.getPrototypeOf 去访问
  • [[prototype]]:和 __proto__ 一样,一般出现在一些书籍和规范中,在浏览器控制台打印也会显示这个,但我们没法用代码访问

constructor

constructor 构造函数,原型对象 prototype 中有 constructor,指向该原型的构造函数。

为什么通过 prototype 修改原型实现继承后要重置 custructor?

我们可以通过将一个构造函数的 prototype 指向另一个构造函数来实现继承父类的属性和方法,但是往往还会额外加一个 Child.prototype.constructor = Child,这是因为直接通过 prototype 修改了原型后,当前子类原型里的 constructor 实际上还是指向的父类构造函数(因为 prototype 本来就是父类的),这不就和我们上面说的 "原型对象 prototype 中有 constructor,指向该原型的构造函数" 相矛盾了。

代码语言:javascript
复制
function Person(username, age) {
  this.username = username
  this.age = age || 0
  this.say = function() {
    console.log('Hello, 我是' + username)
  }
}
function Boy(gender) {
  this.gender = gender
}
Boy.prototype = new Person('小明')
// 重置 constructor
// Boy.prototype.constructor = Boy
const ming = new Boy()
ming.say()
// 直接通过调实例原型上的构造函数去新建实例
const hua = new ming.constructor()
console.log(hua)
// 打印 2 个实例上的构造函数名都是父类的 Person
console.log(ming.__proto__.constructor.name) // Person
console.log(hua.constructor.name) // Person

当我们不重置 constructor 的时候,通过 constructor.name 可以看到此时都是指向父类的,加上 Boy.prototype.constructor = Boy 重置后就能正确指向子类了。

其实这一点对于我们正常使用、实例化对象、继承都是没啥影响的,不过建议是按照规范重置成正确的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 秘密菜单 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档