15-JavaScript高级程序设计-创建对象

2023-05-16

一、创建对象

创建单个对象:Object构造函数[new Object()]、对象字面量(参见8-Object&Array)
创建多个对象:以下7种方式

1.工厂模式

function createPerson(name, age, job){
  var o = new Object();
  o.name = name;
  o.age = age;
  o.job = job;
  o.sayName = function(){
    alert(this.name);
  };
  return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");

优缺点:
解决了创建多个相似对象的问题,
没有解决对象识别的问题(即怎样知道一个对象的类型)。

2.构造函数模式

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = function(){
    alert(this.name);
  };
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

与 createPerson() 不同之处:

  • 没有显式地创建对象;
  • 直接将属性和方法赋给了 this 对象;
  • 没有 return 语句。

注意:函数名首字母大写。

创建 Person 的新实例,必须使用 new 操作符。
以这种方式调用构造函数实际上会经历以下 4 个步骤:
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。

将构造函数当做函数

任何函数,只要通过 new 操作符来调用,那它就可以作为构造函数;
任何函数,如果不通过 new 操作符来调用,那它跟普通函数没什么两样。

构造函数的问题

相比工厂模式优点:可以将构造函数的实例标识为一种特定的类型
主要问题:每个方法都要在每个实例上重新创建一遍
解决方法:将函数定义转移到构造函数外面,但是在全局作用域定义不合适,使用原型模式。

3.原型模式

每个函数都有一个 prototype (原型)属性,这个属性是一个指针,指向一个对象。
用途:让所有对象实例共享它所包含的属性和方法。

function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
  alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true
理解原型对象

只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象
在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。

创建了自定义的构造函数之后,其原型对象默认只会取得 constructor 属性;其他方法都是从 Object 继承而来的。

构造函数、原型、实例三者关系:

prototype
constructor
__prpto__
new出来
构造函数
原型
实例

Person.prototype.constructor == Person

isPrototypeOf() 判断原型对象是否是实例的原型:
Person.prototype.isPrototypeOf(person1) // true

Object.getPrototypeOf() 获取实例的原型:
Object.getPrototypeOf(person1)
浏览器支持:IE9+、Firefox 3.5+、Safari 5+、Opera 12+ 和 Chrome。

读取某个对象的某个属性时,先从对象实例本身开始,找到了则返回;没找到则继续搜索原型对象。
==> 多个实例可以共享原型的属性和方法

hasOwnProperty() 检测一个属性是否存在于实例本身中(不在原型上)
person1.hasOwnProperty("name")

原型与 in 操作符

使用 in 操作符的2种方式:单独使用 和 在for-in循环中使用。

  • key in object
    单独使用时,in 操作符会在通过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原型中。

*判断属性是原型中的属性(不在实例上):

function hasPrototypeProperty(object, name){
  return !object.hasOwnProperty(name) && (name in object);
}
  • for (var key in object) { }
    使用 for-in 循环时,返回的是所有能够通过对象访问的、可枚举的属性,其中既包括存在于实例中的属性,也包括存在于原型中的属性。

IE早期版本bug:屏蔽(理解为实例上重写了该属性)不可枚举属性的实例属性不会出现在 for-in 循环中。
不可枚举属性:hasOwnProperty()、propertyIsEnumerable()、toLocaleString()、toString()、valueOf();constructor 和 prototype(后2个ECMAScript 5,不是所有浏览器都实现)

  1. 获取对象上所有可枚举的实例属性:Object.keys(对象)
    返回一个包含所有可枚举属性的字符串数组
    var keys = Object.keys(obj);
  2. 获取所有实例属性(无论是否可枚举):Object.getOwnPropertyNames()
    var keys = Object.getOwnPropertyNames(Person.prototype) // ['constructor','name','age','job','sayName']
  3. 浏览器支持:IE9+、Firefox 4+、Safari 5+、Opera 12+ 和 Chrome。
更简单的原型语法

用一个包含所有属性和方法的对象字面量来重写整个原型对象。
出现问题: 原型对象上的 constructor 属性不再指向预想中的构造函数(Person),指向 Object 构造函数
解决方法(如需要):手动设置 constructor : Person

Person.prototype = {
  constructor : Person,  // 导致[[Enumerable]]特性被设置为true
  name : "Nicholas",
  age : 29,
  job: "Software Engineer",
  sayName : function () {
    alert(this.name);
  }
};

兼容 ECMAScript 5 的 JavaScript 引擎可以使用 Object.defineProperty()

// 重设构造函数,只适用于 ECMAScript 5  兼容的浏览器
Object.defineProperty(Person.prototype, "constructor", {
  enumerable: false,
  value: Person
});
原型的动态性

实例与原型之间的松散连接关系 ==>
可以随时为原型添加属性和方法,修改能够立即从实例上反映出来。

重写整个原型对象,结果不同(实例指向的是旧的原型)
把原型修改为另外一个对象:等于切断了构造函数与最初原型之间的联系。
注意:实例中的指针仅指向原型,而不指向构造函数。
重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系(这些实例引用的仍然是最初的原型)。

原生对象的原型

所有原生引用类型(Object、Array、String,等等)都在其构造函数的原型上定义了方法,如 Array.prototype 的 sort() 方法。
可以修改原生对象的原型,可以随时添加方法。
不推荐修改原生对象的原型。

原型对象的问题
  • 所有实例在默认情况下都将取得相同的属性值
  • 最大问题是由其共享的本性所导致:函数共享很合适,基本值属性也没问题,但对于包含引用类型值的属性问题比较突出
    例如:原型属性有一个是数组,给一个实例的数组添加一项,所有数组都变了
    ====> 不单独使用原型模式

4.组合使用构造函数模式和原型模式 ☆☆☆☆☆

构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。
混成模式支持向构造函数传递参数

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.friends = ["Shelby", "Court"];
}
Person.prototype.sayName = function(){
  alert(this.name);
}
// Person.prototype = {
//   constructor : Person,
//   sayName : function(){
//     alert(this.name);
//   }
// }
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false

5.动态原型模式

动态原型模式是为了解决独立的构造函数和原型的困惑。
把所有信息都封装在了构造函数中,通过在构造函数中初始化原型(仅在必要的情况下),保持了同时使用构造函数和原型的优点。

function Person(name, age, job){
  //属性
  this.name = name;
  this.age = age;
  this.job = job;
  // 方法 --以下方法代码只会在初次调用构造函数时才会执行
  if (typeof this.sayName != "function"){
    Person.prototype.sayName = function(){
      alert(this.name);
    };
  }
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); // 弹框 Nicholas

该模式可以使用 instanceof 操作符确定它的类型。

6.寄生构造函数模式

基本思想:创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象;但从表面上看,这个函数又很像是典型的构造函数。

function Person(name, age, job){
  var o = new Object();
  o.name = name;
  o.age = age;
  o.job = job;
  o.sayName = function(){
    alert(this.name);
  };
  return o;
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"

和工厂模式高度一致,除了使用 new 操作符并把使用的包装函数叫做构造函数之外。

该模式返回的对象与构造函数或者与构造函数的原型属性之间没有关系。
不能依赖 instanceof 操作符来确定对象类型。
不建议使用。

7.稳妥构造函数模式

稳妥对象:没有公共属性,方法也不引用 this 的对象。
稳妥构造函数遵循与寄生构造函数类似的模式,有两点不同:一是新创建对象的实例方法不引用 this ;二是不使用 new 操作符调用构造函数。

function Person(name, age, job){
  //创建要返回的对象
  var o = new Object();
  //可以在这里定义私有变量和函数
  //添加方法
  o.sayName = function(){
    alert(name);
  };
  //返回对象
  return o;
}
var friend = Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"

除了使用 sayName() 方法之外,没有其他办法访问 name 的值。

即使有其他代码会给这个对象添加方法或数据成员,也不可能有别的办法访问传入到构造函数中的原始数据。==> 安全性

稳妥构造函数模式创建的对象与构造函数之间也没有什么关系,因此 instanceof 操作符对这种对象也没有意义。


上一篇:14-JavaScript高级程序设计-理解对象
下一篇:16-JavaScript高级程序设计-继承

全书整理版:《Javascript高级程序设计》第3版(总结版)


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

15-JavaScript高级程序设计-创建对象 的相关文章

  • Sonic_cli常用命令

    用户名 xff1a admin 密码 xff1a YourPaSsWoRd 一 change password admin 64 sonic passwd Changing password for admin current UNIX p
  • SONIC config_db.json文件的前生今世

    config db json的使用 系统启动时从config db json中读取数据并写入CONFIG DB数据库 xff0c 前提是config db json存在 xff1b 保存当前系统的一些配置信息 xff0c 通过config
  • SONiC架构DOCKER组件交互分析

    BGP组件交互分析 内核中的bgp socket收到BGP更新报文 xff0c 然后被上送到bgpd进程bgpd处理该报文 xff0c 并通知zebra进程新增前缀和关联下一跳zebra确定该目的可达后 xff0c 生成一个路由网络链接信息
  • sonic处理netlink事件

    sonic处理netlink事件 sonic在处理路由 xff0c 接口up down 接口地址变化 xff0c team等事件上极大的依赖内核 sonic通过监听rtnl事件来响应linux事件 从而感知相关信息变化 libnl soni
  • sonic配置team与实现机制

    sonic实现team代码框架图 xff1a sonic修改lag模式配置步骤 1 修改文件teamd j2 docker exec it teamd bash cd usr share sonic templates vim teamd
  • asyncComputed 异步计算属性

    asyncComputed 异步计算属性 我们项目中最近使用了异步计算属性 xff0c 个人感觉很好用 xff0c 特此推荐给大家 一 案例 假设这样一个场景 xff1a 一个列表数据 data 是通过接口返回 xff0c 请求参数中有一个
  • sonic管理口信息处理流程

    sonic管理口信息处理流程 管理接口信息配置文件格式 管理信息使用MGMT INTERFACE 表进行配置 对象的key由管理接口名字和IP前缀使用 连接而成 属性 gwaddr用于执行默认路由指向管理口 xff0c 其值为默认网关 属性
  • SONIC VLAN配置流程

    SONIC VLAN配置流程 sonic vlan配置通过订阅config db的键空间事件完成vlan配置信息从config db到内核和硬件 config db json格式如下 xff1a 34 VLAN 34 34 Vlan1000
  • sonic容器构建

    sonic中大量的组件运行在docker容器中 xff0c 用于隔离彼此的运行环境 xff0c 从而解决相互之间的互斥问题 下面我们分析一下sonic中各个容器的构建过程 Dockerfile文件的生成过程 sonic中的容器Dockerf
  • ARM Cortex-M底层技术(九)KEIL MDK 分散加载示例1-更改程序运行基址

    KEIL MDK 分散加载示例1 更改程序运行基址 小编我一向主张在实战中学习 xff0c 不主张直接去去学习规则 amp 定义 xff0c 太枯燥 xff0c 在实际应用中去摸索 xff0c 才会真正理解具体的技术细节 xff0c 下面我
  • 如何修改已提交commit信息

    如何修改已提交commit信息 1 修改commit信息 1 1 修改最后一次提交信息 通过git log查看提交历史信息 xff1a 输入命令 xff1a span class token function git span commit
  • linux 安装mysql 以及常见错误总结

    安装的方法菜鸟教程上有 xff1a 入口 mysqld initialize 命令是出现如下错误Fatal error Please read 34 Security 34 section of the manual to find out
  • elementui下拉框多选报[Vue warn]: <transition-group> children must be keyed: <ElTag>

    elementui下拉框多选 xff0c 选值报错 选中一个值后所有的值都会被选中 经检查 xff0c 是由于我的下拉框的value值为一个对象而非单个值 值为对象时需要填入value key span class token operat
  • Hadoop_1 入门WordCount

    记录踩得坑以及部署环境流程 搭建的是伪分布Hadoop 首先环境需要安装zookeeper 这个好装 xff0c 不多说其次比较复杂的是安装openssh 我的Linux系统是centos 7 mini版本 安装openssh之前的准备工作
  • PX4无人机控制

    PX4无人机控制 向话题 mavros setpoint raw local发布无人机目标位置 43 偏航 xff0c 或者目标速度 43 偏航 发布目标位置 43 偏航 xff1a mission span class token pun
  • npm install 报错:gyp verb `which` failed Error: not found: python

    今天新启动一个项目 xff0c 在 npm install 安装依赖项时出现报错 npm install span class token operator gt span husky 64 span class token number
  • 24_ZYNQ7020开发板_SPI与Qflash芯片读写

    内核中使用spi master表示一个SPI主机控制器 一 SPI控制器驱动 1 xff09 spi master申请与释放 SPI申请 span class token keyword struct span spi master spa
  • python3的input函数实现回车换行,而不是结束输入

    span class token comment 实现回车换行 xff0c 而不是结束 span endstr span class token operator 61 span span class token string 34 34
  • rviz-Ros Wiki官网教程学习笔记(1)-用户指南

    0 rviz介绍 rviz是ROS自带的图形化工具 xff0c 可以很方便的让用户通过图形界面开发调试ROS 参考官网 rviz UserGuide 1 安装 根据自己的版本号 xff0c 在下面选择对应的命令执行 以ROS melodic
  • 轻松搭建CAS 5.x系列(6)-在CAS Server上增加OAuth2.0协议

    概述说明 CAS Server默认搭建出来 xff0c 客户端程序只能按照CAS自身的协议接入 CAS的强大在于 xff0c 有官方的插件 xff0c 可以支持其他的协议 本章节就让CAS Server怎么增加OAuth2 0的登录协议 安

随机推荐

  • 一起DIY四轴飞行器(二)初识飞控大脑

    系统 xff1a Windows 硬件 xff1a xff08 1 xff09 STM32F103C8T6最小系统板 某宝上搜索 STM32F103最小系统 xff0c 如上图所示这样的 xff08 2 xff09 ST LINK v2下载
  • STM32CubeMX基于HAL库点亮LED灯

    开发环境 xff1a Windows 软件 xff1a 1 STM32CubeMX 6 3 0 2 MDK 5 14 一 cubeMX的基本配置 1 选择MCU 2 配置时钟 查看电路图 xff0c 8MHz的高速外部晶振接到 OSCIN
  • 一起DIY四轴飞行器(三)添加实时操作系统--freeRTOS

    开发环境 xff1a Windows 软件 xff1a 1 STM32CubeMX 6 3 0 2 MDK 5 14 一 初识freeRTOS系统 1 什么是FreeRTOS xff1f Free 即免费的 xff0c RTOS 全称是 R
  • ESP8266 初次使用

    一 工具 1 ESP8266 01S 淘宝上搜索ESP8266 01S 引脚说明 xff1a 2 USB转串口 给设备供电3 3V xff08 官方说不要用USB转串口的3 3V xff0c 需要单独供电 xff09 xff0c USB转串
  • ubuntu安装boost

    ubuntu安装boost 系统 Ubuntu 18 04 boost中 xff0c 用到了别的函数库 xff0c 所以为了使用boost中相应的功能 xff0c 需要先安装系统中可能缺失的库 1 卸载已经安装的boost 删除 usr l
  • 简单的状态机图

    一 什么是状态机 xff1f 做产品的时候 xff0c 我们总能遇到一些比较复杂的逻辑问题 比如状态的转换 xff0c 字段状态的确认 xff0c 权限的控制 xff0c 状态的对应 而普通的流程图 xff0c 或时序图 xff0c 更侧重
  • js-对象转基本类型

    起因是收到朋友发的一道题 xff0c 如下 xff1a span class token comment 请在问号处填写你的答案 使下方等式成立 span span class token keyword let span a span c
  • 局域网内wakeonlan远程唤醒其它计算机

    背景 xff1a 需要管理多台计算机 xff0c 所有计算机在一个局域网内 xff0c 并且有的安装了Windows系统 xff0c 有的安装了Linux系统 我们想远程关闭和启动所有计算机 关闭计算机直接通过网络发生操作系统关机命令即可实
  • D3D中的三种Buffer

    在D3D中 针对视窗有三种Buffer 它们分别是 Color Buffer Depth Buffer和Stencil Buffer Color Buffer在D3D中又称为Render Target 意思是最后着色的目标Buffer 就是
  • 创建镜像(更新与构建镜像)

    创建镜像 有时从Docker镜像仓库中下载的镜像不能满足我们的要求 xff0c 此时可以基于这个镜像 xff08 基础镜像 xff09 封装一个自 己的镜像 两种方式 xff1a 更新镜像 xff1a 使用docker commit命令构建
  • (十)CMake链接已有的动态库

    使用一个已经存在的动态库 xff0c 需要用到CMake中两个命令 xff0c 分别是 xff1a link directoriestarget link libraries 下面先介绍以下两个命令的格式及其含义 xff0c 最后是一个使用
  • ROS入门21讲笔记(四)自定义话题消息类型和使用

    除了ROS内置消息外 xff0c 我们还能自定义消息 这一次我们不再与海龟较劲 xff0c 而是自定义一个订阅消息类型 xff0c 让订阅者和发布者通过这个结构进行数据通信 一 如何自定义话题消息 xff1f 话题消息是以 msg结尾的文件
  • ROS入门21讲笔记(七)自定义消息消息类型和使用

    这一节主要是学习如何自定义一个服务类型并使用它 一 如何自定义服务消息 xff1f 服务数据是以 srv结尾的文件 xff0c 是一个用于描述ROS服务信息简单文本文件 xff0c 用于生成不同语言消息的源代码 srv文件存放在packag
  • ROS入门21讲笔记(十二)常用可视化工具

    一 QT类可视化工具 1 1 rqt console rqt console 为显示和过滤ROS信息提供了一个GUI插件 1 2 rqt plot rqt plot使用不同的绘图后端提供数值可视化功能 1 3 rqt Image view
  • (二)CMake 使用头文件

    一 include directories 该命令用于增加一个编译头文件 其基本语法是 xff1a include directories span class token punctuation span span class token
  • cargo 宏展开遇到的问题

    最近学习rust xff0c 看到宏展开命令 span class token comment 单独文件 span rustc Z unstable options pretty span class token operator 61 s
  • 工程师笔记|常见的嵌入式软件工程师面试题

    Q xff1a 什么是ISR xff1f A xff1a ISR 是指中断服务程序 这些是存储在特定内存地址的函数 xff0c 当发生某种类型的中断时会调用这些函数 Cortex M 处理器系列具有管理中断执行的 NVIC Q xff1a
  • 计算机中的速率、带宽、时延、利用率解读

    计算机网络的性能一般是指它的几个重要的性能指标 但除了这些重要的性能指标外 xff0c 还有一些非性能特征 xff08 nonperformance characteristics xff09 也对计算机网络的性能有很大的影响 那么 xff
  • 手把手教你写链表,小学生看了都说好~

    摘要 xff1a 明明我们在之前已经接触了数组 xff0c 感到数组已经是万能的数据存储位置了 但是 xff0c 如果我们一直在使用比较复杂的数据 xff08 也就是比较多的数据时 xff09 xff0c 肯定会感到很反感 因为对于数组这种
  • 15-JavaScript高级程序设计-创建对象

    一 创建对象 创建单个对象 xff1a Object构造函数 new Object 对象字面量 xff08 参见8 Object amp Array xff09 创建多个对象 xff1a 以下7种方式 1 工厂模式 span class t