prototype (原型) 属性

卫衣 / 双肩包 / T 恤/羽绒服等任选,下单送 CSDN 年卡 程序员周边任选一款实物,直接赠送 CSDN 会员年卡+ Coding Plan,写代码学习装备一起拿下 立即抢购

转自:https://www.jianshu.com/p/4f87d28923ce

这篇文章是基于 <<JavaScript 高级程序设计>>第六章面向对象的程序设计 6.2.3原型模式

我们每创建一个函数, 都有一个 prototype (原型)属性, 这个属性是一个指针, 指向一个对象,这个对象的 用途: 包含可以由指定类型的所有实例共享的属性和方法
所以 prototype 就是通过调用构造函数而创建的哪个对象实例的原型对象

function Person() {};
Person.prototype.name = 'TonNi';
Person.prototype.age = 19;
Person.prototype.sayName = function () {
    alert ( this. name );
}

var person1 = new Person();
person1.sayName() // TonNi;

// prototype.isPrototypeOf 判断 person1 实例的原型是不是 Person
console.log (Person.prototype.isPrototypeOf(person1))  // true

//  Object.getPrototypeOf 该方法获取一个对象的原型
console.log(Object.getPrototypeOf(person1) === Person.prototype) // true 
console.log(Object.getPrototypeOf(person1).name) //TonNi

// hasOwnProperty 检测一个实例属性是不是存在与实例中 , 存在返回true
person1.sing = 'i can sing';
console.log(person1.hasOwnProperty('name')) // false 
console.log(person1.hasOwnProperty('sing')) // true 

1: 什么是实例, 什么是原型 ?

以上面的代码为例,
原型: 就是 大写的 Person 函数
实例: 就是以 Person为原型 从新 new 出来的person; 上例中的 person1就是实例

这里我们将 name, age, sayName() 等属性和方法 直接添加到了 Personprototype 中, 这样所有 new 出来的实例 都拥有同样的 属性和方法, 可以被访问或调用. var person2 = new Person() person2 和 person1 一样拥有同样的属性和方法

2: constructor

只要创建一个新的函数, 就会根据特定规则为该函数创建一个 prototype 属性, 此属性指向函数的原型对象
而在默认情况下, 所有的原型对象都会自动获得一个 constructor (构造函数) 属性, 这个属性是一个指向 prototype 属性所在函数的指针.
可以看下图, Person.prototype.constructor 指向的就是 Person

结构

作用:
通过这个构造函数, 我们还可以继续为原型对象添加其他属性和方法

3: 如果实例中和原型都有同名的属性或者方法, 调用哪个呢?

当代码读取某个属性或者方法时, 都会经行一次搜索, 搜索目标是给定的属性或方法的名字. 搜索顺序是, 先从实例查找 , 如果实例中有, 则返回属性值或者调用方法, 如果没有, 则搜索指针指向原型对象, 如果有同上, 如果没有, 属性就返回 undefind, 方法则报错, xxx is not a function

function Person() {};
Person.prototype.name = 'TonNi';
Person.prototype.age = 19;
Person.prototype.sayName = function () {
    alert ( this. name );
}

var person1 = new Person();
console.log(person1.name) //  'TonNi'   实例中没有则去原型中找, 找到后返回属性值,

person1.name = 'Mike'
console.log(person1.name) // Mike 实例中有了name 就直接拿来用了

//在实例化一个person2
var person2 = new Person()
console.log(person2 .name) //  'TonNi'   实例中没有则去原型中找, 找到后返回属性值, 不会因为 person1添加了name收到影响

// 删除person1中的name
delete person1.name;
console.log(person1.name) //  'TonNi'  删除后 实例中没有则去原型中找, 找到后返回属性值,

故当我们为实例添加一个属性时,此属性会屏蔽掉原型中对象中的同名属性, 但是只会阻止我们访问对象原型属性, 并不会修改

4: 关于判断属性或方法是存在实例还是原型中

  • hasOwnProperty() 只有属性或方法 在实例中才为 true
...上面的例子
person1.hasOwnproperty('name');  //  false  不在实例中

person1.name = 'Mike';
person1.hasOwnProperty('name'); // true 在实例中, 返回true
  • in操作符
    无论该属性在实例中还是原型中, 只要能访问到就返回 true
...上上面的例子
'name' in person1 // true;
person1.hasOwnproperty('name');  //  false  不在实例中

person1.name = 'Mike';
'name' in person1 // true;
person1.hasOwnProperty('name'); // true 在实例中, 返回true

'run' in person1; // false 实例和原型都没有 

所以呢, 同时使用 hasOwnProperty()in 就可以确定该属性到底存在对象还是原型中了

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

由于 in 操作符只要通过对象能够访问到属性就能返回 true, hasOwnProperty() 只要属性存在实例中才能返回 true, 所以只要 in 返回 truehasOwnProperty() 返回 false 就说明属性在原型中

5: 更简单的原型语法

由于上面例子每添加一个属性就敲一次 Person.prototype 很麻烦, 为了减少不必要的输入, 如下:

function Person () {}
Person.prototype = {
    name: 'Toni',
    age: 19,
    sayName: function () {
        console.log(this.name);
    }
}

缺点1:
按照上面的对象字面量来重写整个原型对象, 最终结果相同, 但是, constructor 属性不在指向 Person, 这里重写了后, constructor 指向了新对象 Object构造函数 不在指向 Person, 尽管 instanceof 还能返回正确的结果, 但是 constructor 已经无法确定对象类型了
如:

//上例
var friend = new Person();
console.log(friend  instanceof Object)// true
console.log(friend  instanceof Person)// true

console.log(friend.constructor == Person) // false  正常的此处应为true
console.log(friend.constructor == Object) // true

改进:
如果你的确需要 constructor属性的话, 可以这样:

function Person () {}
Person.prototype = {
    constructor: Person,     //这里 
    name: 'Toni',
    age: 19,
    sayName: function () {
        console.log(this.name);
    }
}

或者 使用 Object.defineProperty()

function Person () {}
Person.prototype = {
    name: 'Toni',
    age: 19,
    sayName: function () {
        console.log(this.name);
    }
}

Object.defineProPerty (Person.prototype, 'constructor', {
    enumerable: false,
    value: Person
})
  • 第一种方法: 有个问题就是, 把原本 constructor 属性的 Enumerable 设置成了 true 成了可枚举的属性, 原生的是 false 不可枚举
  • 第二中方法, 则是重构构造函数, 直接设置了 enumerable: false, 但是 只适应于 ECMAScript 5 兼容的浏览器

缺点2或者是需注意:
看例子:
例子1

var friend = new Person();    // 先实例化一个Person原型
Person.prototype.sayHi = function () { 
    console.log('Hi')
};                                        // 添加方法

friend.sayHi();  // Hi     没什么问题

例子2:

function Person () {};    //原型

var friend = new Person(); //  紧接着实例化  (注意这里实例的顺序)

Person.prototype = {
    constructor: Person,    
    name: 'Toni',
    age: 19,
    sayName: function () {
        console.log(this.name);
    }
}                                             // 然后在添加属性方法

friend.sayName()              // 报错 friend.sayName is not a function

例子2正确的顺序是:

function Person () {};    //原型

Person.prototype = {
    constructor: Person,   
    name: 'Toni',
    age: 19,
    sayName: function () {
        console.log(this.name);
    }
}                                             // 然后在添加属性方法

var friend = new Person();    //  实例化

friend.sayName()              //  'Toni';

例子错误原因

例子1中, 因为实例与原型中链接的是一个指针, 而非一个副本, 所以不论实例化原型与添加属性方法的顺序如何, 都是可以在原型中获取到

例子2中, 我们先创建一个Person 的一个实例, 然后又重写了其原型对象,
但是, 重写原型对象就切断了现有原型与任何之前已经存在的对象实例之间的联系

6: 原型对象的问题

原型对象的缺点 , 所有的实例都在默认情况下获取相同的属性值, 即共享本性, 虽然这也是其优点, 但是这中共享对于函数非常适合, 对于包含基本值(即 name: 'tom',)的属性还算可以, 但是对于引用类型(Object, Array,String, ...)的属性问题就比较突出了
如:

function Person () {};    

Person.prototype = {
    constructor: Person,   
    name: 'Toni',
    age: 19,
    friends: ['Tom', 'mike', 'Anny'],
    sayName: function () {
        console.log(this.name);
    }
}                                             

var friend1 = new Person();   
var friend2 = new Person();   

console.log (friend2 .friends) //'Tom', 'mike', 'Anny'   正常显示

friend1 .friends.push('Masa');   // 使用实例1 在数组中添加一个人名 

console.log (friend2 .friends) //'Tom', 'mike', 'Anny' ,'Masa'  , person2受到了影响

当然了如果你要的结果就是这样, 那倒无所谓, 如果不是, 都需要单独的属性的话, 就有很大问题,

问题原因自然是由于实例与原型中链接的是一个指针, 指向同一个数组, friend1 对原型的修改, friend2 也会反映出来

7: 所以最好组合是

组合使用 构造函数模式 和原型模式,
构造函数模式用于定义实例属性,
原型模式用于定义方法和共享属性,

// 构造函数, 定义实例属性,  this将作用域指向新对象
function Person (name,age) {
    this.name = name;
    this.age = age;
    this.friends = ['Tom', 'Mike'];
}

//原型模式用于定义方法和共享属性,
Person.prototype = {
    constructor: Person,
    sayName: function () {
        console.log(this.name)
    }
}

var person1 = new Person ('Toni', 19) ;
var person2 = new Person ('Anny', 18);

person1.friends.push('An');
console.log(person1.friends);  // 'Tom', 'Mike','An'
console.log(person2.friends) ; //  'Tom', 'Mike', 

例子中, 实例属性都是在构造函数中定义的, 而由所有实例共享的属性 construction 和 方法 sayName 都是在原型中定义的, 因而, 修改 person1.friends 数组, 只是修改实例中的数组, 没有修改共有属性,, 所以其他实例不会受到影响



作者:有情怀的程序猿
链接:https://www.jianshu.com/p/4f87d28923ce
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

2026年最新扬州市公交线路及站点矢量数据.zip 数据格式:shp 数据坐标:GCJ02 数据更新时间:2026年9月 公交线路来源:8684网站 https://8684.com.cn/ 站点数据来源:高德API接口 数据打开方式:QGIS或Arcgis 站点数据字段:名称、序号、对应线路、几何信息 线路数据字段:名称、类型、起点、终点、开始时间、结束时间、起步价、全价、长度、公司、几何信息 立即下载

相关推荐

Desktop-Crm-Reconciliation-Exception-Drill-v1.0-原创源码与文档.zip

原创 JavaScript 离线工具,包含完整源码、README、MIT LICENSE、原创与授权声明、自动化测试、示例数据、真实运行截图及离线报告。解压后运行 npm test 验证,再用 node src/cli.js examples/sample.json 生成报告;不依赖外部服务。

如何快速上手ruadapt_qwen2.5_3B_finetuned_v4-openmind:从安装到推理的完整指南

想要快速上手**ruadapt_qwen2.5_3B_finetuned_v4-openmind**俄语AI模型吗?这篇终极指南将带你从零开始,轻松掌握这个强大的开源语言模型的安装、配置和推理全过程。ruadapt_qwen2.5_3B_finetuned_v4-openmind是基于Qwen2.5 3B架构的俄语微调版本,专为OpenMind平台优化,支持NPU硬件加速,能够高效处理俄语文本生成

gitblog_00883的博客 948

Developer-Stack-Inventory-Handoff-Evidence-v1.0-原创源码与文档.zip

原创 JavaScript 离线工具,包含完整源码、README、MIT LICENSE、原创与授权声明、自动化测试、示例数据、真实运行截图及离线报告。解压后运行 npm test 验证,再用 node src/cli.js examples/sample.json 生成报告;不依赖外部服务。

ruadapt_qwen2.5_3B_finetuned_v2-openmind终极俄语AI助手完整指南

你是否正在寻找一款强大的俄语AI助手?ruadapt_qwen2.5_3B_finetuned_v2-openmind正是你需要的终极解决方案!这款基于Qwen2.5架构的3B参数俄语优化模型,专为俄语自然语言处理任务设计,支持OpenMind框架和NPU硬件加速,为俄语用户提供了前所未有的AI助手体验。无论你是开发者、研究人员还是普通用户,这款俄语AI模型都能帮助你高效处理俄语文本任务。 ##

gitblog_00482的博客 757

如何快速上手ruadapt_qwen2.5_3B_finetuned_v4-openmind:俄罗斯语大语言模型的终极优化版本深度解析

俄罗斯语大语言模型ruadapt_qwen2.5_3B_finetuned_v4-openmind是一个基于Qwen2.5-3B架构的专业微调版本,专门针对俄罗斯语文本生成任务进行了深度优化。这个开源模型在OpenMind框架上运行,为开发者提供了强大的俄罗斯语自然语言处理能力,特别适合需要处理俄语内容的AI应用场景。 ## 🚀 模型核心特性速览 ruadapt_qwen2.5_3B_fin

gitblog_01029的博客 788

终极指南:如何掌握ruadapt_qwen2.5_3B_finetuned_v4-openmind的Prompt工程与生成控制技巧

**ruadapt_qwen2.5_3B_finetuned_v4-openmind** 是一个专门针对俄语优化的先进语言模型,基于强大的Qwen2.5 3B架构进行微调。这个模型在OpenMind平台上表现出色,特别适合俄语文本生成、对话系统和内容创作任务。作为一款3B参数规模的模型,它在保持高效推理速度的同时,提供了卓越的语言理解和生成能力。 ### 🔑 核心关键词 - **ruadapt

gitblog_00015的博客 469

ruadapt_qwen2.5_3B_finetuned_v2-openmind微调实战:如何定制你的俄语AI助手

想要打造一个专为俄语优化的AI助手吗?ruadapt_qwen2.5_3B_finetuned_v2-openmind是一个基于Qwen2.5-3B模型微调的俄语专用大语言模型,专门针对俄语场景进行了深度优化。这个开源项目提供了完整的微调实战指南,帮助你快速上手定制自己的俄语AI助手,无论是客服对话、内容创作还是技术文档翻译,都能轻松应对。🚀 ## 🔥 为什么选择ruadapt_qwen2.

gitblog_00061的博客 551

【太阳能多级逆变器】具有较低的总谐波失真(THD),并采用了SPWM(正弦脉宽调制)技术研究(Simulink仿真实现)

内容概要:本文研究了一种应用于太阳能发电系统的多级逆变器,旨在通过采用正弦脉宽调制(SPWM)技术有效降低输出电压的总谐波失真(THD),从而提升电能质量。研究基于Simulink平台构建了完整的仿真模型,系统地实现了SPWM信号生成、驱动逻辑控制以及多电平输出波形合成等关键环节,验证了该多级逆变器在不同运行工况下具备优异的动态响应能力和稳定性。仿真结果表明,所设计的逆变器能够输出接近理想正弦波的电压波形,显著抑制高次谐波,满足可再生能源并网对电能质量的严苛要求,体现出多级逆变拓扑在光伏发电系统中的技术先进性与工程应用价值。; 适合人群:电气工程、自动化、新能源科学与工程及相关专业的本科生、研究生,以及从事光伏逆变器设计、电力电子变换技术和可再生能源并网系统研发的工程技术人员。; 使用场景及目标:①深入理解多级逆变器的工作原理及其在太阳能发电系统中的关键作用;②掌握SPWM调制技术的理论基础与实现方法,并分析其对改善THD的核心机制;③借助Simulink仿真平台开展电力电子电路的建模、参数调试与性能评估,服务于课程设计、毕业设计、科研课题或实际工程项目开发。; 阅读建议:建议读者结合提供的Simulink仿真模型进行同步操作与验证,细致调整调制比、载波频率等关键参数,观察其对输出波形和THD指标的影响,以深化对系统动态特性的理解,并尝试优化控制策略以进一步提升系统性能。

AI8H1K08 PWM AND AD OLED INT test Altium Designer PCB

AI8H1K08 PWM AND AD OLED INTOtest Altium Designer PCB

15_日期偏移计算工具类(Java企业级代码

一个开箱即用的 Java 日期偏移计算工具类 DateOffsetUtils,基于 JDK17 新时间 API(java.time.LocalDate)编写、无第三方依赖。支持基于给定日期计算 n 天后的日期,n 为负即 n 天前、为 0 返回当天,自动正确处理跨月、跨年以及闰年(如 229 日)。同时提供 LocalDate 与字符串两套入口,字符串默认 yyyy-MM-dd 格式并支持自定义格式,解析失败抛出带原因的明确异常。类采用 final 加私有构造、DateTimeFormatter 静态复用保证线程安全、Objects 入参校验、完整 JavaDoc,规范对标阿里巴巴 Java 开发手册,粘贴进 Spring Boot 3.x 项目即可用于有效期计算、到期日推算、账单周期等业务场景。

VCF 生成器 Lite v6.0.0 通讯录生成工具 支持批量导入通讯录

VCF 生成器 Lite v6.0.0:批量导入与功能拓展 VCF 生成器 Lite v6.0.0 正式版已发布,此次更新带来了批量导入手机通讯录这一重要功能,极大地方便了用户整理和管理联系人信息。同时,新增了多项功能,如翻译所有 CLI 内容,让不同语言背景的用户都能更好地使用;verbose 模式新增更多日志信息,有助于用户更详细地了解操作过程。 此外,还添加了多地区号码格式支持,包括中国港澳台地区电话号码格式,满足了不同地区用户的需求。当未捕获异常时,系统会自动保存错误日志,并引导用户反馈给开发者,这体现了产品团队对用户体验 的重视,有助于及时发现和解决问题。 修复痛点:引号清理与进度条显示问题 在修复方面,此次更新解决了引号清理功能在包含换行符时的错误行为,以及自 `v4.3.0` 版本以来的进度条显示问题。这些问题虽然看似微小,但却影响了用户的使用体验,修复后能让用户更加顺畅地使用 VCF 生成器 Lite。 代码与文档重构:提升可维护性与易用性 在变更方面,将翻译框架迁移到 gettext,提升了 `LANGUAGE` 环境变量 优先级,方便用户根据自己的语言偏好进行设置。在 AI 的指导下重构项目,使得各层次职责更加清晰,代码更加模块化,可维护性更高,这为产品的后续发展奠定了良好的基础。 同时,按 Diataxis 框架重构用户文档,按开发生命周期 重组开发者文档,让用户和开发者都能更方便地获取所需信息,提高了产品的易用性。 编辑观点:VCF 生成器 Lite v6.0.0 的更新在功能、修复和代码文档方面都有显著提升,满足了用户的实际需求,增强了产品的竞争力,未来有望在市场上取得更好的成绩。

libcms.so 10.4 version

代码下载链接: https://pan.quark.cn/s/2bb176eb6a52 版本号为10.4的libcms.so文件,属于Unix系统(一种操作系统)的动态链接库,是一种二进制文件,其功能与Windows操作系统中的.dll文件相似

2026 年高教社杯全国大学生数学建模竞赛B 题 无线电干扰源的快速自动定位与清除(数学建模,代码,论文免费分享)

内容概要:本文围绕2026年高教社杯全国大学生数学建模竞赛B题“无线电干扰源的快速自动定位与清除”展开,提供完整的数学建模方案、配套代码实现与论文撰写资源。内容涵盖问题分析、模型构建、算法设计与仿真验证全过程,并延伸至多类相关科研方向的Matlab/Simulink仿真实例,如无人机路径规划、微电网优化调度、信号处理、电力系统无功优化、时频冲突消解等,充分展示复杂工程问题的建模与求解方法。资源通过百度网盘及微信公众号“荔枝科研社”免费共享,旨在为参赛学生与科研人员提供系统性技术支持与创新启发。; 适合人群:全国大学生数学建模竞赛参赛者,具备一定数学建模、编程基础(尤其是Matlab/Simulink)的本科生与研究生,以及从事智能优化、通信工程、电力系统、信号处理、路径规划等相关领域研究的科研人员。; 使用场景及目标:①辅助完成数学建模竞赛中关于无线电干扰源定位与清除等问题的建模、编程与论文撰写;②获取多种科研课题的高质量代码实现与论文参考范例,提升科研效率与创新能力;③学习先进优化算法(如GWO、WOA、NSGA-III等)在复杂系统优化中的应用方法;④借鉴多学科交叉问题的建模思路与仿真技术。; 其他说明:所有资源均可通过提供的百度网盘链接及公众号免费获取,建议用户按照目录结构系统性地浏览与学习,结合代码运行与论文阅读进行实践,以深入掌握建模范式与算法实现细节,充分发挥资源的学习价值与科研参考价值。

2026年最新邢台市公交线路及站点矢量数据.zip

数据格式:shp 数据坐标:GCJ02 数据更新时间:2026年9月 公交线路来源:8684网站 https://8684.com.cn/ 站点数据来源:高德API接口 数据打开方式:QGIS或Arcgis 站点数据字段:名称、序号、对应线路、几何信息 线路数据字段:名称、类型、起点、终点、开始时间、结束时间、起步价、全价、长度、公司、几何信息

声控灯学习记录20260908

声控灯学习记录20260908

2、基础-基本电路知识(电路知识、基本元器件).pptx

2、基础-基本电路知识(电路知识、基本元器件)

2026网信玄盾珠峰网络安全技能大赛决赛竞赛手册.docx

2026网信玄盾珠峰网络安全技能大赛决赛竞赛手册.docx

基于模型预测MPC控制和卡尔曼滤波的空调加热器、室内温度调节(Matlab代码实现)

内容概要:本文系统研究了基于模型预测控制(MPC)与卡尔曼滤波相结合的空调加热器及室内温度调节方法,并提供了完整的Matlab代码实现。通过建立精确的热力学动态模型,采用MPC算法进行多步预测与滚动优化,实现对室内温度的最优控制策略,在保证舒适度的同时提升能源效率。为应对系统中存在的测量噪声与状态不可测问题,引入卡尔曼滤波器对关键状态变量进行实时估计与噪声抑制,显著增强了系统的鲁棒性与控制精度。文中详细阐述了MPC控制器的设计流程,涵盖预测模型构建、目标函数设定、约束条件处理及二次规划求解方法,同时深入分析了卡尔曼滤波在状态估计中的融合机制。通过Matlab仿真实验验证了该复合控制策略在多种工况下的稳定性、抗干扰能力与节能潜力,结果表明其在智能建筑温控、工业加热系统等领域具有广泛的应用前景。; 适合人群:具备自动控制理论基础和Matlab编程能力的科研人员、研究生及自动化、电气工程、暖通空调等相关专业的高年级本科生。; 使用场景及目标:①学习并掌握模型预测控制(MPC)在典型温控系统中的建模与实现方法;②理解卡尔曼滤波在状态估计中的作用及其与先进控制算法的协同机制;③应用于智能家居、绿色建筑、工业过程控制等需要高精度、高能效温度调节的实际工程场景。; 阅读建议:建议读者结合提供的Matlab代码逐模块分析算法实现细节,重点关注MPC的预测时域、控制时域设置、代价函数权重调优以及卡尔曼滤波的协方差初始化与增益收敛过程,动手复现并修改仿真参数,以深入理解先进控制策略的设计思想与工程折衷。

Video-Generation-Delivery-Handoff-Evidence-v1.0-原创源码与文档.zip

原创 JavaScript 离线工具,包含完整源码、README、MIT LICENSE、原创与授权声明、自动化测试、示例数据、真实运行截图及离线报告。解压后运行 npm test 验证,再用 node src/cli.js examples/sample.json 生成报告;不依赖外部服务。

上一篇: js settimeout()
下一篇: tp5系列一tp5多应用修改
wiscourper_
博客等级 码龄17年 1641粉丝 272原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值