博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈JS对象的创建、原型、原型链继承
阅读量:6802 次
发布时间:2019-06-26

本文共 4387 字,大约阅读时间需要 14 分钟。

JS的内置对象,可分为两类:

  • 数据封装类对象:Object、Boolean、Number、String、Array
  • 其他对象:Function、Date、Error、Math、RegExp、Arguments

自然,除了内置对象外,可以通过JS代码自定义对象。

先总结下创建对象的方式,每种方式继承的原型对象不同:

  • 构造函数:原型为构造函数的prototype属性
  • Object.create():原型为传入的第一个参数,若第一个参数为null,以Object.prototype为原型;第二个参数为可选的属性描述符

下面分别看一下代码示例:

1. 构造函数方式

function Phone(brand) {  this.brand = brand}let nokia = new Phone('Nokia')console.log(nokia.constructor === Phone); // trueconsole.log(nokia.constructor.prototype === Phone.prototype); // trueconsole.log(Phone.prototype.__proto__ === Object.prototype); // true => the final relationship between Phone() and Object()console.log('Object.prototype.__proto__: ', Object.prototype.__proto__); // nullfunction Smartphone(model) {  this.model = model}let iphone8 = new Smartphone('iphone8')console.log(iphone8.constructor === Smartphone); // true// prototype继承Smartphone.prototype = new Phone('Huawei')let honor = new Smartphone('honor')console.log(honor.constructor === Smartphone); // falseconsole.log(honor.constructor === Phone); // trueconsole.log(honor.brand); // Huawei => 继承了brand属性console.log(honor.model); // honor// 直接以字面量形式声明时,相当于构造函数为Objectlet ironman = {name: 'Tony Stark'}console.log(ironman.constructor === Object) // trueconsole.log(ironman.constructor.prototype === Object.prototype) // true复制代码

2. 利用Object.create()

// 建立一个原型为null的对象let spiderman = Object.create(null, {  props: {    name: 'Peter Park'  }});console.log(spiderman.constructor); // => undefined    // 创建一个原型为Array的对象let array = Object.create(Array.prototype, {});console.log(array.constructor); // => Array()console.log(array.constructor.prototype); // => [constructor: ƒ, ...]// 创建一个原型为自定义类的对象function Car() {  this.fix = function() {    console.log('going to fix');  }}let audi = Object.create(Car.prototype, {});audi.ov = '3.0T'Car.prototype.charge = function() {  console.log('going to charge');}console.log(audi.constructor); // Car()console.log(audi.constructor.prototype); // {charge: ƒ, constructor: ƒ}复制代码

js通过对原型的操作,可以模拟高级语言对象中的继承特性:

  • prototype是函数层面的属性,隐性原型属性__proto__是对象(包括函数)层面的属性。
  • 一个对象的__proto__,即是其构造器函数的prototype。
  • prototype作为一个对象,亦拥有__proto__属性,指向的是更上一层构造器函数的prototype。
  • 直到__proto__指向的是最上层的Object.prototype,且到此后,Object.prototype.__proto__的值为null。
  • JS的新版本趋势中,逐步开始模拟高级语言(特别是Java)的特性,描述实例成员、静态成员、继承等特性,越来接近面向对象编程。

进一步看下prototype继承:

将某个类的prototype指向为某个对象后,此类将会继承该对象的所有实例成员,静态成员除外。看例子:

function Phone(brand) {  this.brand = brand  this.online = function() {    console.log(brand + ' is going to online');  }}let nokia = new Phone('Nokia')console.log(nokia.__proto__ === nokia.constructor.prototype); // true => 对象的__proto__即是其构造器的prototypeconsole.log(nokia.constructor.prototype.__proto__ === Object.prototype); // trueconsole.log('prototype of nokia: ', nokia.prototype); // undefined => 可再次看出prototype是构造器层面的属性,且__proto__是对象层面的属性nokia.online(); // Nokia is going to onlinePhone.prototype.onMsg = function() {  console.log('nokia message coming');}nokia.onMsg(); // nokia message comingfunction Smartphone(model) {  this.model = model  this.oncalling = function() {    console.log(model + ' is on calling');  }}let iphone8 = new Smartphone('iphone8')iphone8.oncalling(); // iphone8 is on calling// 继承方式之一:// 此方式优缺点:简单易于实现, 但若为子类新增属性和方法,要在赋值了prototype之后执行, 无法实现多继承Smartphone.prototype = new Phone('Xiaomi') // 继承Phone对象实例的所有成员,静态成员除外let iphoneX = new Smartphone('iphoneX')console.log(iphoneX.brand); // Xiaomiconsole.log(iphoneX.model); // iphoneXiphoneX.online(); // Xiaomi is going to onlineiphoneX.onMsg(); // nokia message comingiphoneX.oncalling(); // iphoneX is on callingconsole.log(iphoneX instanceof Phone); // true console.log(iphoneX instanceof Smartphone); // true复制代码

顺带提一下call方法也可以实现继承:

function Animal(name){     this.name = name;     this.showName = function(){       console.log(this.name);     }   }   function Cat(name){    Animal.call(this, name);  }    var cat = new Cat("Black Cat");   cat.showName(); // Black Cat复制代码

进一步看下原型链

function Ball(name){  this.name = name;  this.showName = function () {    console.log('I am ' + this.name + ' from this');   }}Ball.prototype.showName = function () {  console.log('I am ' + this.name + ' from prototype'); }let football = new Ball("football");football.fly = function () {  console.log(this.name + ' is flying');}football.fly(); // football is flying// 先从自身找,找不到在__proto__中去找,没找到,去找上层__proto__,直到结果为null为止football.showName(); // I am football from this复制代码

转载地址:http://mjfwl.baihongyu.com/

你可能感兴趣的文章
《实施Cisco统一通信管理器(CIPT1)》一第2章 部署模型
查看>>
《SolidWorks 2013中文版完全自学手册》——2.4 尺寸标注
查看>>
《Adobe Photoshop CS4中文版经典教程》—第1课1.4节在Photoshop中还原操作
查看>>
《IPv6精髓(第2版)》——3.8 链路本地地址和站点本地地址
查看>>
《深入浅出iPhone/iPad开发(第2版)》——使用GUI编辑器连接UI控制到代码
查看>>
【秒懂设计模式】总述及工厂模式
查看>>
《数据科学:R语言实现》——3.10 重塑数据
查看>>
《抓住听众心理——演讲者要知道的100件事》一16.时间是相对的
查看>>
运维前线:一线运维专家的运维方法、技巧与实践1.8 运维自动化依赖的团队模型...
查看>>
《树莓派渗透测试实战》——第1章 树莓派和Kali Linux基础知识
查看>>
《圣殿祭司的ASP.NET4.0专家技术手册》----1-7 HTML5与CSS3的支持
查看>>
数据结构之链表
查看>>
八年了必须放手了,我不是你妈妈
查看>>
Eric S. Raymond 五部曲
查看>>
《Ansible权威指南 》一2.7 本章小结
查看>>
《iOS编程指南》——2.4节安装iOS SDK
查看>>
Comparing Mongo DB and Couch DB
查看>>
《配置管理最佳实践》——1.6 工具的选择
查看>>
前端工程师如何快速的开发一个微信JSSDK应用
查看>>
Apache Spark源码走读(九)如何进行代码跟读&使用Intellij idea调试Spark源码
查看>>