JS中创建对象有几种方法

news2024/9/19 11:18:13

除了使用Object构造函数或者字面量都可以创建对象,但是也有缺点就是使用同一个接口创建很多对象,会产生大量的重复代码。

1. 工厂模式

简单来说就是把Object创建对象使用函数进行封装,然后再返回创建的对象,就可以创建多个相同对象。

function createPerson(name, age) {
	var o = new Object();
	o.name = name;
	o.age = age;
	o.sayName = function () {
		alert(this.name);
	}
	return o;
}
var person1 = createPerson('张三', 18);

函数createPerson根据参数创建了一个包含所有必要信息的Person对象,可以多次调用这个函数,每次调用都能返回一个对象。

工厂模式缺点: 没有解决对象识别问题,就是怎样知道一个对象的类型。

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('张三', 18, '前端工程师');

1. 什么是构造函数

构造函数本身跟普通函数一样,也不存在定义构造函数的特殊语法。唯一区别在于调用的方式不同,任何函数只要通过new 操作符来调用,都可以叫做构造函数。默认情况下构造函数的首字母大写,不大写也没有问题,主要是为了与普通函数区分。

2. 为什么有构造函数

为了创建对象而已,本身就是一个函数。

3. 创建一个新实例经历的过程

创建实例,必须使用new操作符调用。

  • 创建一个新对象
  • 将构造函数的作用域赋给新对象(也就是修改this,将this指向这个新对象)
  • 执行构造函数中的代码(给对象新增属性方法)
  • 返回新对象

3. 构造函数比其他函数区别

通过new操作符调用就叫做构造函数,如果不通过new操作符调用就是普通函数。一般构造函数默认首字母大写,不大写也没事,主要是为了区分是构造函数还是普通函数。

4. 构造函数比工厂模式的优点

自定义的构造函数将来可以将它的实例标识为一种特定的类型。

5. 构造函数比工厂模式的不同之处

  • 没有显式创建对象,也就是new Object
  • 直接将属性和方法赋给了this对象
  • 没有return语句

6. 构造函数的问题

每个方法都要在每个实例上重新创建一遍

3. 原型模式

function Person() {}
Person.prototype.name = '张三';
Person.prototype.age = 18;
Person.prototype.job = '前端工程师';
Person.prototype.sayName = function () {
	alert(this.name);
}
var person1 = new Person();
person1.sayName(); // '前端工程师'

1. 原型对象

创建一个新函数都会有一个prototype(原型)属性,这个属性指向函数的原型对象。

prototype原型属性

在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针(也就是构造函数)。创建一个自定义构造函数之后,其原型对象默认只会取得constructor属性,其他方法,则会从Object继承而来的。

constructor属性

当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。这个指针(内部属性)叫做[[Prototype]],可以通过_proto_进行或者。用它来连接实例与构造函数的原型对象。

proto

1. 原型对象的好处

可以让所有对象实例共享它所包含的属性和方法,换句话说,不必在构造函数中定义对象实例的信息,而是直接将这些信息添加到原型对象中。

2. isPrototypeOf()

用来检测实例是否指向某个原型对象,返回布尔类型

Person.prototype.isPrototypeOf(person1); // true

3. Object.getPrototypeOf()

返回原型对象

Object.getPrototypeOf(person1) == Person.prototype; // true
Object.getPrototypeOf(person1.name); // '张三'

4. 如何读取属性值

当对象某个对象属性时,首先先从对象实例本身开始读取,如果存在就返回,不存在就开始向原型对象查找属性。

5. 对象实例保存访问属性注意点

虽然实例对象可以对属性进行添加、编辑等操作,但是不能重写原型中的值。如果在实例中添加一个与原型中属性同名的属性,只是会把原型中对应的属性屏蔽掉。访问值时,会访问实例新创建的这个属性值,如果将实例对象中的这个属性删除,则会访问到原型中该属性的值。

hasOwnProperty()用来检测一个属性是否存在实例中还是原型中,返回布尔类型,若在实例中返回true。

person1.hasOwnProperty('name'); // false
person1.name = '李四';
person1.hasOwnProperty('name'); // true

2. 原型与in操作符

in操作符可以单独使用,也可以在for…in中使用。

**单独使用时:**判断能否访问到某个属性,不管这个属性在实例上还是原型中,返回布尔类型。

'name' is person1; // true

可以与hasOwnProperty()一起使用,来判断某个属性存在对象还是原型中。

function hasPrototypeProperty(object, name) {
	return !object.hasOwnProperty(name) && (name in object);
}

hasOwnProperty只有在实例时才回返回true,in只要任意存在都返回true。

若hasOwnProperty为true,则结果返回false,代表在实例中。

若hasOwnProperty为false,in为true, 则结果返回true,代表在原型中。

若都为false,则结果返回false,代表不存在

**for…in: **返回的是所有可枚举的属性,包括实例、原型中存在的。

3. 更简单的原型语法

前面的例子每添加一个属性或方法都要敲一遍Person.prototype。可以用一个包含所有属性和方法的对象字面量来重写整个原型对象。

function Person(){}
Person.prototype = {
	name: '张三',
	age: 18,
	job: '前端工程师',
	sayName: function() {
		alert(this.name);
	}
}

这样看着是简单了,但是其实是用对象字面量又重新创建了一个新对象,这时的constructor属性将不再执向Person了。因为每创建一个函数,都会创建它的prototype对象,这个对象也会自动获得constructor属性。

这里本质重写了默认的prototype对象,因此constructor属性也变成了新对象的constructor属性(也就是Object构造函数), 不再执行Person函数。

解决方法

可以通过修改constructor属性值进行解决。

Person.prototype.constructor = Person;

简单原型语法

但是这样修改会使其属性的描述特性[[Enumerable]]被设置成true,默认原生的属性是不可枚举的,所以可以使用Object.defineProperty()进行设置属性值。

Object.defineProperty(Person.prototype, 'constructor', {
	enumerable: false,
	value: Person
})

4. 原型的动态性

动态性指的是不管创建实例在设置原型前后,都能获取到原型中的属性和方法。

但是有一种情况则不行,那就是重写了对象原型,重写也是用字面量重写设置了一个新对象(上一个标题3)。

为什么重写了对象原型就不能获取属性和方法了呢?

因为在调用构造函数时就为实例添加了一个指针,指向最初的原型对象,所以说修改原型对象就等于切断了构造函数和最初原型之间的联系。

实例中的指针指向原型,而不指向构造函数。

5. 原生对象的原型

原型模式不仅仅体现在创建自定义类型,就连原生的引用类型也是采用这种模式,都是在其构造函数的原型上定义的方法。

通过原生对象的原型,不仅可以取得所有默认方法的引用,也能定义新方法,也可以修改原生对象的原型就像修改自定义对象的原型。

6. 原型对象的问题

  • 它省略了为构造函数传递初始化参数的这一环节,造成所有实例在默认情况下都将取得相同的属性值。
  • 最大问题是其共享的本质导致的

不懂,以后编写

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

**用法:**构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。

**结果: **每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省内存,并且还支持向构造函数传递参数。

function Person(name, age, job) {
	this.name = name;
	this.age = age;
	this.job = job;
	this.friends = ['a', 'b'];
}
Person.prototype = {
	constructor: Person,
	sayName: function () {
		alert(this.name);	
	}
}

var person1 = new Person('张三', 18, '前端工程师');
var person2 = new Person('李四', 10, '后端工程师');

person1.friends.push('c');
console.log(person1.friends); // ['a', 'b', 'c']
console.log(person2.friends); // ['a', 'b']
console.log(person1.friends === person2.friends); // false
console.log(person1.sayName === person2.sayName); // true

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);
		}
	}
}

不懂?后面添加

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('张三', 18, '前端工程师');
friend.sayName(); // '张三'

在这个例子中,Person函数创建了一个对象,并设置相应的属性和方法初始化这个对象,然后又返回这个对象。

特点:除了使用new操作符并把使用的包装函数叫做构造函数之外,这个模式跟工程模式其实是一模一样的。

构造函数在没有返回值的情况下,默认返回新对象实例,而添加return语句,则可以重写构造函数时的返回值。

说明:返回的对象与构造函数或者构造函数的原型属性之间没有关系,也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。所以不能依赖instanceof操作符来确定对象类型。

7. 稳妥构造函数模式

指的是没有公共属性,而且其方法也不引用this对象。
与寄生构造函数类似的模式,但也有不同,一是新创建对象的实例方法不引用this。二是不使用new操作符调用构造函数。

function Person(name, age, job) {
    // 创建要返回的对象
    var o = new Object();
    // 定义私有变量和函数
    // 添加方法
    o.sayName = function () {
        alert(name);
    }
    // 返回对象
    return o;
}
var friend = Person('张三', 18, '前端工程师');
friend.sayName(); // '张三'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1061687.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用hugo+github搭建免费个人博客

使用hugogithub搭建免费个人博客 前提条件 win11电脑一台电脑安装了git电脑安装了hugogithub账号一个 个人博客本地搭建 初始化一个博客 打开cmd窗口,使用hugo新建一个博客工程 hugo new site blogtest下载主题 主题官网:themes.gohugo.io 在上面…

快手直播显示请求过快

快手直播显示请求过快 问题描述情况一问题描述原因分析解决方案:情况二问题描述解决方法问题描述 在使用快手直播网页版时,如果我们的请求过于频繁,系统可能无法及时显示所需内容。这种情况下,我们会收到一个稍后重试的提示。一般有两种情况。一种是直接返回一段json,里面…

园林园艺服务经营小程序商城的作用是什么

园林园艺属于高单价服务,同时还有各种衍生服务,对企业来说,多数情况下都是线下生意拓展及合作等,但其实线上也有一定深度,如服务售卖或园艺产品售卖等。 基于线上发展可以增强获客引流、品牌传播、产品销售经营、会员…

云原生微服务 第六章 Spring Cloud中使用OpenFeign

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 文章目录 系列文章目录前言1、OpenFeign的实现…

mybatis-plus控制台打印sql(mybatis-Log)

配置了mybatis-plus.configuration.log-implorg.apache.ibatis.logging.stdout.StdOutImpl;但是mybatis执行的sql没有输出 需要检查点: 1、日志级别设置:请确保你的日志级别配置正确。如果日志级别设置得太低,可能导致SQL语句不…

软件工程与计算总结(四)项目管理基础

目录 一.项目和项目管理 二.团队组织与管理 三.软件质量保障 四.软件配置管理 五.项目实践 一.项目和项目管理 1.软件开发远不是纯粹的编程,随着软件规模的增长,软件开发活动也变得越来越复杂~ 2.软件项目就是要将所有的软件开发活动组织起来&#…

云原生Kubernetes:K8S集群kubectl命令汇总

目录 一、理论 1.概念 2. kubectl 帮助方法 3.kubectl 子命令使用分类 4.使用kubectl 命令的必要环境 5.kubectl 详细命令 一、理论 1.概念 kubectl是一个命令行工具,通过跟 K8S 集群的 API Server 通信,来执行集群的管理工作。 kubectl命令是操…

嵌入式Linux裸机开发(一)基础介绍及汇编LED驱动

系列文章目录 文章目录 系列文章目录前言IMX6ULL介绍主要资料IO表现形式 汇编LED驱动原理图初始化流程时钟设置IO复用设置电气属性设置使用GPIO 编写驱动编译程序编译.o文件地址链接.elf格式转换.bin反汇编(其他) 综合成Makefile完成一步编译烧录程序imx…

分词.join 保存txt

要求 分词.join 保存txt 第1种方法 分词.join 保存txt input多行文本 /storage/emulated/0/数据中心/txt没有就新建为什么会想到这么做 1. 是因为有分词文件📄要处理 2. 对各种词语和线索进行分类 3. 解释一下生活中不常见的现象,但是深刻的符合社会…

十月四日作业

1、服务器 头文件&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器头文件 #include <QTcpSocket> //客户端头文件 #include <QList> //链表容器 #include <…

基于混合蛙跳优化的BP神经网络(分类应用) - 附代码

基于混合蛙跳优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于混合蛙跳优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.混合蛙跳优化BP神经网络3.1 BP神经网络参数设置3.2 混合蛙跳算法应用 4.测试结果…

全屋灯具选购指南,如何选择合适的灯具。福州中宅装饰,福州装修

灯具装修指南 灯具就像我们家里的星星&#xff0c;在黑暗中带给我们明亮&#xff0c;可是灯具如果选择的不好&#xff0c;这个效果不仅体现不出来&#xff0c;还会让人觉得烦躁。 灯具到底该怎么选呢&#xff1f;装修灯具有哪些注意事项呢&#xff1f;给大家做了一个总结&#…

集群服务器

文章目录 项目名:实现集群服务器技术栈通过这项目你学到(或者复习到)实现功能编码环境json环境muduo库boost库MySql数据库登录mysql&#xff1a;查看mysql服务开启了没有&#xff1f;mysql的服务器及开发包库chat&#xff0c;表 allgroup friend groupuser offlinemessage user…

【吞噬星空】第四季出现技术事故,巴巴塔变秃头,提升质量成笑话

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 《吞噬星空》动画第四季复播了&#xff0c;而且还是连播两集&#xff0c;不少粉丝都表示这次看爽了&#xff0c;不过在看爽了的同时&#xff0c;这一季的不少细节也引起了大家广泛的关注和讨论。这部动画作品以…

引入短信服务

一、阿里云短信服务 进入阿里云平台&#xff0c;然后选择短信服务&#xff0c;通过API发送短信(需要充值金额&#xff0c;几块钱就可以&#xff0c;我们仅仅是小规模项目) 找到openAPI 可以看到Java语言的代码模板&#xff0c;这个就是Java SendSMS短信服务的代码 创建Accessk…

电机-电力拖动-振动-应力分析-设备防护知识初步

1.涉及领域和课程&#xff1a; 信号与系统现代自动化原理与应用频谱转换及振动分析材料学基础与应力分析数学建模、仿真与求解工程数学传感器机器学习与模式识别随机信号处理反馈系统文献学DSP应用机器视觉凸优化&#xff0c;数学物理方法 2.教材推荐 豆瓣书单&#xff0c;更…

【云备份项目】【Linux】:环境搭建(g++、json库、bundle库、httplib库)

文章目录 1. g 升级到 7.3 版本2. 安装 jsoncpp 库3. 下载 bundle 数据压缩库4. 下载 httplib 库从 Win 传输文件到 Linux解压缩 1. g 升级到 7.3 版本 &#x1f517;链接跳转 2. 安装 jsoncpp 库 &#x1f517;链接跳转 3. 下载 bundle 数据压缩库 安装 git 工具 sudo yum…

很普通的四非生,保研破局经验贴

推免之路 个人情况简介夏令营深圳大学情况机试面试结果 预推免湖南师范大学面试结果 安徽大学面试结果 北京科技大学笔试面试结果 合肥工业大学南京航空航天大学面试结果 暨南大学东北大学 最终结果一些建议写在后面 个人情况简介 教育水平&#xff1a;某中医药院校的医学信息…

英语——分享篇——每日100词——601-700

disastrous——adj.灾难性的&#xff0c;完全失败的——disast(e)r灾难(熟词)ous藕丝(拼音)——灾难性的地震后大家只能吃藕丝 disorder——n.骚乱&#xff0c;混乱&#xff1b;vt.使失调——dis的士(谐音)order命令(熟词)——的士司机命令我稳住那场骚乱 distract——vt.转移…

C++设计模式-工厂模式(Factory Method)

目录 C设计模式-工厂模式&#xff08;Factory Method&#xff09; 一、意图 二、适用性 三、结构 四、参与者 五、代码 C设计模式-工厂模式&#xff08;Factory Method&#xff09; 一、意图 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。Factory…