对象进阶、原型-原型链

news2024/11/15 19:56:26

工厂方法创建对象

我们之前已经学习了如何创建一个对象,那我们要是想要创建多个对象又该怎么办?聪明的同学可能会说,直接在写几个对象不就好了吗?比如下边的代码:

var person1 = {
    name: "孙悟空",
    age: 18,
    sayName: function () {
        console.log(this.name);
    }
};

var person2 = {
    name: "猪八戒",
    age: 19,
    sayName: function () {
        console.log(this.name);
    }
};

var person3 = {
    name: "沙和尚",
    age: 20,
    sayName: function () {
        console.log(this.name);
    }
};

console.log(person1);
console.log(person2);
console.log(person3);

的确,上述代码确实可以创建多个对象,但是,这样的解决方案真的好吗?对于少量对象可能使用,我们假设说,要用循环创建1000个对象,那你这种办法似乎就没用了,我们可以这么做,如下代码:

//使用工厂模式建立对象
function createdPerson(){   
          //创建对象
          var obj =new Object();
          //设置对象属性
          obj.name="孙悟空",
          obj.age="18",
          obj.sayName=function(){

          console.log(this.name);   
    };
    //返回对象
    return obj 
  
}

var person1 = createPerson("孙悟空", 18);
var person2 = createPerson("猪八戒", 19);
var person3 = createPerson("沙和尚", 20);

console.log(person1);
console.log(person2);
console.log(person3);

现在再看上述代码,发现好像已经完美的解决了创建多个对象的难题,那我们是不是可以用循环批量创建1000个对象了呢?那我们就来试试:

// 使用工厂模式创建对象
function createPerson(name, age) {
    // 创建新的对象
    var obj = new Object();
    // 设置对象属性
    obj.name = name;
    obj.age = age;
    // 设置对象方法
    obj.sayName = function () {
        console.log(this.name);
    };
    //返回新的对象
    return obj;
}

for (var i = 1; i <= 1000; i++) {
    var person = createPerson("person" + i, 18);
    console.log(person);
}

这样我们就实现了批量创建对象的功能,至于对象的名称和年龄,我们可以通过名称数组和年龄数组来获取,但这并不是我们本小节的重点,我们就忽略了。 

用构造函数创建对象

你会发现我们所创建的对象类型都是Object,具体代码如下:

// 使用工厂模式创建对象
function createPerson(name, age) {
    // 创建新的对象
    var obj = new Object();
    // 设置对象属性
    obj.name = name;
    obj.age = age;
    // 设置对象方法
    obj.sayName = function () {
        console.log(this.name);
    };
    //返回新的对象
    return obj;
}

for (var i = 1; i <= 1000; i++) {
    var person = createPerson("person" + i, 18);
    console.log(typeof person);
}

那这有问题吗?看起来有,看起来好像又没有,每创建一个都是对象,但是在实际生活中,人应该是一个确定的类别,属于人类,对象是一个笼统的称呼,万物皆对象,它并不能确切的指明当前对象是人类,那我们要是既想实现创建对象的功能,同时又能明确所创建出来的对象是人类,那么似乎问题就得到了解决,这就用到了构造函数,每一个构造函数你都可以理解为一个类别,用构造函数所创建的对象我们也成为类的实例,那我们来看看是如何做的:
 

// 使用构造函数来创建对象
function Person(name, age) {
    // 设置对象的属性
    this.name = name;
    this.age = age;
    // 设置对象的方法
    this.sayName = function () {
        console.log(this.name);
    };
}

var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙和尚", 20);

console.log(person1);
console.log(person2);
console.log(person3);

那这构造函数到底是什么呢?我来解释一下:

构造函数:构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写,构造函数和普通函数的还有一个区别就是调用方式的不同,普通函数是直接调用,而构造函数需要使用new关键字来调用。

那构造函数是怎么执行创建对象的过程呢?我再来解释一下:

调用构造函数,它会立刻创建一个新的对象
将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象
逐行执行函数中的代码
将新建的对象作为返回值返回
你会发现构造函数有点类似工厂方法,但是它创建对象和返回对象都给我们隐藏了,使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。我们将通过一个构造函数创建的对象,称为是该类的实例。

现在,this又出现了一种新的情况,为了不让大家混淆,我再来梳理一下:

当以函数的形式调用时,this是window
当以方法的形式调用时,谁调用方法this就是谁
当以构造函数的形式调用时,this就是新创建的那个对象
我们可以使用 instanceof 运算符检查一个对象是否是一个类的实例,它返回true或false

语法格式:

对象 instanceof 构造函数
console.log(person1 instanceof Person);

原型
使用构造函数的方式进行创建对象,但是,它还是存在一个问题,那就是,你会发现,每一个对象的属性不一样这是一定的,但是它的方法似乎好像是一样的,如果我创建1000个对象,那岂不是内存中就有1000个相同的方法,那要是有10000个,那对内存的浪费可不是一点半点的,我们有没有什么好的办法解决,没错,我们可以把函数抽取出来,作为全局函数,在构造函数中直接引用就可以了,上代码:

// 使用构造函数来创建对象
function Person(name, age) {
    // 设置对象的属性
    this.name = name;
    this.age = age;
    // 设置对象的方法
    this.sayName = sayName
}

// 抽取方法为全局函数
function sayName() {
    console.log(this.name);
}

var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙和尚", 20);

person1.sayName();
person2.sayName();
person3.sayName();

但是,在全局作用域中定义函数却不是一个好的办法,为什么呢?因为,如果要是涉及到多人协作开发一个项目,别人也有可能叫sayName这个方法,这样在工程合并的时候就会导致一系列的问题,污染全局作用域,那该怎么办呢?有没有一种方法,我只在Person这个类的全局对象中添加一个函数,然后在类中引用?答案肯定是有的,这就需要原型对象了,我们先看看怎么做的,然后在详细讲解原型对象。

// 使用构造函数来创建对象
function Person(name, age) {
    // 设置对象的属性
    this.name = name;
    this.age = age;
}

// 在Person类的原型对象中添加方法
Person.prototype.sayName = function() {
    console.log(this.name);
};

var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙和尚", 20);

person1.sayName();
person2.sayName();
person3.sayName();

那原型(prototype)到底是什么呢?

我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象,即显式原型,原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。

如果函数作为普通函数调用prototype没有任何作用,当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__(隐式原型)来访问该属性。当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。

以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。


原型链

访问一个对象的属性时,先在自身属性中查找,找到返回, 如果没有,再沿着__proto__这条链向上查找,找到返回,如果最终没找到,返回undefined,这就是原型链,又称隐式原型链,它的作用就是查找对象的属性(方法)。

我们使用一张图来梳理一下上一节原型案例的代码:

// 使用构造函数来创建对象
function Person(name, age) {
    // 设置对象的属性
    this.name = name;
    this.age = age;
}

Person.prototype.height =10;
var a = new Person();

a._proto_=== Person.prototype  // true
Person===Person.protype.constructor  // true
Object.getPrototype(person1) === Person.prototype //true


当我们使用 a 的

 注意:Object对象是所有对象的祖宗,Object的原型对象指向为null,也就是没有原型对象

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

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

相关文章

2核2G3M轻量服务器腾讯云和阿里云怎么选择?

2核2G3M轻量应用服务器选阿里云还是腾讯云&#xff1f;腾讯云2核2G3M轻量应用服务器95元一年&#xff0c;阿里云2核2G3M配置优惠价108元一年&#xff0c;如何选择&#xff1f;阿腾云详细对比阿里云和腾讯云轻量应用服务器2核2G3M配置CPU性能及选择方法&#xff1a; 目录 轻量…

基于STM32F103+思岚A1激光雷达的扫描仪

前言 一个朋友在做服务机器人项目&#xff0c;用到思岚的激光雷达&#xff0c;于是便把淘汰的A1M8雷达送我一个&#xff0c;本着拿到啥就玩啥的态度&#xff0c;必须整一波。其实激光雷达还是搭配ROS才能发挥最大的作用&#xff0c;奈何资源有限&#xff0c;实力不足&#xff…

STM32 USB CDC VPC

STM32 USB CDC VPC 关键字 STM32,STM32CubeMX,HAL库,USB,虚拟串口,串口不定长接收 1.简介 通过使用stm32cubemx&#xff0c;实现USB CDC虚拟串口&#xff0c;并与硬件串口进行数据传输&#xff0c;实现了硬件串口数据的不定长接收&#xff0c;以及USB虚拟串口超过64字节的数…

钉钉H5微应用基础学习

钉钉开发文档 一、使用调试工具——IDE&#xff1a; 1、先下载调试工具&#xff0c;并且新建一个企业内部应用。 如果需要管理员权限&#xff0c;可以自己创建一个企业。 &#xff08;tips&#xff1a;一定要屏蔽自己创建的企业的消息&#xff0c;不然消息很多&#xff09; 2…

Burpsuite超详细安装教程

概述 Burp Suite 是用于攻击web 应用程序的集成平台&#xff0c;包含了许多工具。Burp Suite为这些工具设计了许多接口&#xff0c;以加快攻击应用程序的过程。所有工具都共享一个请求&#xff0c;并能处理对应的HTTP 消息、持久性、认证、代理、日志、警报。 接下来我来给大…

Linux4.8Nginx Rewrite

文章目录 计算机系统5G云计算第六章 LINUX Nginx Rewrite一、Nginx Rewrite 概述1.常用的Nginx 正则表达式2.rewrite和location3.location4.实际网站使用中&#xff0c;至少有三个匹配规则定义5.rewrite6.rewrite 示例 计算机系统 5G云计算 第六章 LINUX Nginx Rewrite 一、…

看完一位毕业的拼多多“P9”级别员工以及他的四页半简历,我悟了

前几天在脉脉上看到一个热帖&#xff0c;是刚从PDD毕业的P9级别员工吴可发的&#xff0c;同时附上了他的简历&#xff0c;这个简历很有意思&#xff0c;基本上和国内互联网这十多年来的发展步骤重叠&#xff0c;能够反映出&#xff0c;在这样一个跌宕起伏的时代里&#xff0c;个…

一次有关 DNS 解析导致 APP 慢的问题探究

一、业务背景 HTTTPDNS AWS Router53 APP 使用 HTTPDNS&#xff0c; 为解决 DNS 解析生效慢&#xff0c; DNS 劫持等问题。 我们 IOS 和安卓都是使用了 HTTPDNS。 域名托管在 AWS Router53。 域名有多个解析(基于延迟)&#xff0c;为了解决就近接入。 示例配置 ai.baidu.c…

网易Java后端面经(一面)

这是网易的Java一面&#xff0c;问的都很基础。 1.session过期怎么处理&#xff1f; session过期通常指用户在一段时间内没有进行任何操作而导致session失效。针对这种情况&#xff0c;可以采取以下措施&#xff1a; 1. 前端提示用户session即将过期&#xff0c;提醒其重新登录…

JavaScript对象的增强知识

Object.defineProperty ◼ 在前面我们的属性都是直接定义在对象内部&#xff0c;或者直接添加到对象内部的&#xff1a;  但是这样来做的时候我们就不能对这个属性进行一些限制&#xff1a;比如这个属性是否是可以通过delete删除的&#xff1f;这个属性是否在for-in遍历的时候…

微信能取代对讲机吗?区别在哪?

对讲机和微信的区别在哪&#xff1f;为什么大家在通讯方面选择对讲机而不是微信&#xff1f; 微信作为社交软件在多个领域都有着广泛的应用&#xff0c;不过在对讲机行业也在讨论一个话题&#xff1a;微信能否取代对讲机&#xff1f;下面河南宝蓝小编就和大家聊聊这个话题。 …

基于redis实现秒杀并防止超卖

基于redis实现秒杀并防止超卖 为什么基于redis针对秒杀商品库存为一个的情况setnx代码实现测试 针对有多个库存的商品实现测试 为什么基于redis 因为所有redis的操作&#xff08;这里指的是key的操作&#xff0c;像备份落盘之类的另算&#xff09;都是单线程的&#xff0c;所以…

一文读懂:LoRA实现大模型LLM微调

LoRA大模型LLM微调 为什么要进行微调&#xff1f;LoRA思路提高权重更新效率选择低的秩 实现LoRALoRA在LLaMA实现 为什么要进行微调&#xff1f; 在快速发展的人工智能领域中&#xff0c;以高效和有效的方式使用大型语言模型变得越来越重要。 预训练的大型语言模型通常被称为优…

02-启动 Vue 项目

一. 学习目标 掌握 Vue 项目的启动 二. 学习内容 掌握 Vue 项目的启动 三. 学习过程 项目的启动也有两种方式&#xff0c;一种是通过图形界面启动&#xff0c;另一种是通过命令行启动。 1.图形界面 打开vscode编辑器&#xff0c;点击 1.文件 ——>打开文件夹&#xff0c…

springboot实现支付宝支付(沙箱环境)

springboot实现支付宝支付 1. 获取应用id,应用私钥和支付宝公钥2. 开始开发3. 内网穿透4. 测试支付功能 1. 获取应用id,应用私钥和支付宝公钥 进入支付宝控制台:https://open.alipay.com/develop/manage 找到沙箱 这里可以看到应用id 可以看到应用私钥和支付宝公钥,获取这…

Zoho:集成ChatGPT、开发大型语言模型,加紧布局AI+SaaS

在企业的数字化转型进程中&#xff0c;管理层和员工的数字化意识会随着建设的推进而不断提高&#xff0c;对于办公场景的数字化应用需求也不断产生。传统的办公系统建设中&#xff0c;系统的应用能力需要支撑越来越丰富的场景需求。 《今日人工智能》采访到Zoho中国VP兼SaaS事业…

【编程语言 · C语言 · for语句】

for 语句 C语言中&#xff0c;使用for语句也可以控制一个循环&#xff0c;并且在每一次循环时修改循环变量。在循环语句中&#xff0c;for语句的应用最为灵活&#xff0c;不仅可以用循环次数已经确定的情况&#xff0c;而且可以用于循环次数不确定而只给出循环结束条件的情况。…

jenkins构建pipline无法执行shell命令原因

问题表现 新的服务器上&#xff0c;新安装的jenkins&#xff0c;在上面创建了一个pipline项目&#xff0c;脚本里有shell命令&#xff0c;但是jenkins每次执行都卡住&#xff0c;经过尝试&#xff0c;无论多简单的命令都执行不了&#xff0c;cp&#xff0c;mv等都不行&#xf…

华为路由器:ospf协议三张表及邻居建立过程

说明&#xff1a;本篇接上一篇继续讲解 拓扑图 为了方便&#xff0c;我把R1/2/3/4/5的router id改成了回环网卡的IP。 ospf协议三张表 邻居表&#xff08;neighbortable&#xff09; OSPF用邻居机制来发现和维持路由的存在&#xff0c;邻居表存储了双向通信的邻居关系OSPF路…