JavaScript --- [学习笔记] 原型模式

说明

  • 接JavaScript — > [学习笔记]观察者模式 & 理解对象 & 工厂模式 & 构造函数模式
  • 上一篇构造函数模式创建的实例,不同实例的同一个方法是不相等的,为了解决这个问题.出现了原型模式

1. 原型模式

  • 具体做法是,不在构造函数中定义对象实例的信息,而是将这些信息直接添加到原型对象
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"console.log(person1.sayName == person2.sayName);    // true

1.1 理解原型对象

1.1.1 prototype属性和constructor属性

  • 创建一个函数(Person),就会根据一组规则创建一个prototype属性(Person.prototype)
  • prototype上面还要一个constructor属性(必带技能),它(Person.prototype.constructor)指向函数Person
  • prototype属性上的所有属性和方法会被所有使用new操作符生产的实例(person1, person2)共享
  • 实例person1、person2通过new Person得到,会有一个[[Prototype]]的指针(在浏览器中通过__proto__访问),它指向Person.prototype

1.1.2 读取某个属性的顺序

  • 读取属性的模拟函数如下:
// obj是某个对象, attr是该对象的属性
const getVal = (obj, attr) =>{// 如果对象中存在该属性则返回if(obj[attr]) {return obj[attr]} else if (obj.constructor === Object) {// 是Objectreturn undefined} else{// 不是Object,检查其constructor指向的函数if(obj.constructor[attr]){return obj.constructor[attr]} else {// constructor指向的函数中不存在,顺着 __proto__ 属性找下去.getVal(obj.__proto__, attr);}}
}

说明:

  1. 所有通过function声明的函数,都继承自Function
  2. Function继承自Object

1.1.3 说说

通过上面的原型找属性的顺序,可以知道:

  1. 当使用new Person生成实例(person1)的时候,person1会有一个指向Person.prototype的指针__proto__
  2. 当访问person1的属性或方法的时候,先从实例开始寻找,若找到了则返回,否则会顺着__proto__向上寻找

1.2 区分一个属性是否来自原型

需要明白下面2点:

  1. 使用in操作符会返回所有对象上的属性或者方法
  2. 使用hasOwnProperty可以确定一个属性是否来自实例对象
// 判断一个熟悉是否来自原型
const fromPrototype = (obj, attr) {return !obj.hasOwnprototype && (attr in obj);
}

1.3 Object.defineProperty

  • Object.defineProperty: 可以给一个对象添加属性,并对属性进行描述
  • 使用如下:
Object.defineProperty(Person.prototype, "constructor", {enumerable: false,value: Person
})

1.3.1 数据属性和访问器属性

  1. JS中的属性类型分为: 数据属性和访问器属性
  2. 数据属性包括:
  • [[Configurabal]]: 是否能被delete删除
  • [[Numerable]]: 是否能被for-in循环访问属性
  • [[Writeble]]: 是否可以被修改
  • [[Value]]: 属性的值
  1. 访问器属性: Configurable、Numerable、Get(读取时触发) 、Set(修改时触发)

1.3.2 Object.defineProperty的使用

  • 在使用对象字面量对函数的原型进行赋值的时候,会丢失原本的constructor属性
  • 使用Object.defineProperty为它加上constructor属性
function Person () {}
Person.prototype = {name: 'marron',age: 18
}
Object.defineProperty(Person.prototype, constructor, {numerable: false,value: Person
})
  1. constructor是不能被for-in循环访问到的
  2. 在字面量中直接赋值,会被for-in循环访问到

1.4 原型的动态性

  • 可以先创建实例后修改原型
function Person () {};
cosnt friend = new Person();
Person.prototype.sayHi =  () => { console.log('SayHi') };
friend.sayHi();
  • 将上述代码修改为下面:
- Person.prototype.sayHi  = () => { console.log('SayHi') };
+ Person.prototype = {
+ 		sayHi: function () {
+ 			console.log('SayHi');
+ 		}
+ }
  • 此时在调用friend.sayHi会报错: Uncaught TypeError: p1.sayHi is not a function, 原因如下:
  1. 使用new操作符时: 建立了一个指针 proto, 它指向 Person.prototype(这个是默认建立的),假设在空间A中,即此时 person1 先从自己的空间中取数据,若没有则去 A中找
  2. 当对Person.prototype进行字面量赋值时, 它改变的是Person.prototype指针的指向,在上面的一系列操作实际是在空间B中.
  3. 当完成了Person.prototype的字面量赋值后,相当于给Person的原型对象新开辟了一个空间B.而此时person1的__proto__还是指向A.故访问不到B

注:重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系.

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

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

相关文章

网络协议各层概述

网络协议概述 OSI是一个开放性的通信系统互连参考模型,他是一个定义得非常好的协议规范。OSI模型有7层结构,每层都可以有几个子层。 OSI的7层从上到下分别是 7 应用层 6 表示层 5 会话层 4 传输层 3 网络层 2 数据链路层 1 物理层; 其中高层&…

A start job is running for Raise network interface(5min 13s )问题解决方法

命令:sudo vim /etc/systemd/system/network-online.target.wants/networking.service将里面的TimeoutStartSec5min 修改为TimeoutStartSec2sec 然后重启系统,就可以生效了,开机速度很快 转载于:https://www.cnblogs.com/sea-stream/p/98615…

javascript --- 实现对象的深拷贝

浅拷贝和深拷贝 浅拷贝: 只拷贝一层.当对象是复杂数据类型(Object、 Array)时,只拷贝引用深拷贝: 多层拷贝.复杂数据类型,会重新分配内存空间. 实现浅拷贝的2种方法 使用for ... in 实现 var obj {name: marron,age: 18,msg: {sex: "1" } } var o {}; for(let …

Qt与FFmpeg联合开发指南(二)——解码(2):封装和界面设计

与解码相关的主要代码在上一篇博客中已经做了介绍,本篇我们会先讨论一下如何控制解码速度再提供一个我个人的封装思路。最后回归到界面设计环节重点看一下如何保证播放器界面在缩放和拖动的过程中保证视频画面的宽高比例。 一、解码速度 播放器播放媒体文件的时候播…

Bzoj1051 受欢迎的牛

每一头牛的愿望就是变成一头最受欢迎的牛。现在有 N 头牛,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎。这种关系是具有传递性的,如果 A 认为 B 受欢迎,B 认为 C 受欢迎,那么牛 A 也认为牛 C 受欢迎。你的任务是求出…

node --- 模块加载机制

1. Node.js中模块加载机制 1.1 模块查找规则-当模块拥有路径但没有后缀时 require(./find.js); require(./find);require方法根据模块路径查找模块,如果是完整路径,直接进入模块如果模块后缀省略,先找同名JS文件再找同名JS文件夹 require(./find); // 以上会先找到命令行目录…

51Nod 蜥蜴和地下室(搜索)

哈利喜欢玩角色扮演的电脑游戏《蜥蜴和地下室》。此时,他正在扮演一个魔术师。在最后一关,他必须和一排的弓箭手战斗。他唯一能消灭他们的办法是一个火球咒语。如果哈利用他的火球咒语攻击第i个弓箭手(他们从左到右标记)&#xff…

多线程——实现Runnable接口实现一个多线程

实现Runnable接口实现一个多线程 Runnable接口源码: package java.lang; //Runnable接口源码只有一个run方法 public interface Runnable {public abstract void run(); } 实现Runnable的两个多线程类: public class RunnableThread1 implements Runnabl…

javascript --- 文件上传即时预览 闭包实现多图片即时预览

使用javascript原生功能实现,点击上传文件,然后再网页上显示出来 1. 初级显示 1.1 准备一个input标签和一个img标签 <input typefile id"file"> <img id"preview" src"">1.2 js代码如下 // 将上传的图片显示到页面上function sho…

第一次作业:深入Linux源码分析进程模型

一.进程的概念 第一&#xff0c;进程是一个实体。每一个进程都有它自己的地址空间&#xff0c;一般情况下&#xff0c;包括文本区域&#xff08;text region&#xff09;、数据区域&#xff08;data region&#xff09;和堆栈&#xff08;stack region&#xff09;。文本区域存…

关于模型验证那点事儿

今天应笑笑老师之问&#xff0c;做了一个模型验证的例子&#xff0c;发现之前对这个东西的理解太片面&#xff0c;重新整理了一下思路 字段验证优先级高于类验证 什么是类验证呢&#xff1f;就是两个字段组合的验证&#xff0c;比如你Admin不允许修改密码&#xff0c;你修改密码…

mongoose --- createUser

说明 源代码记录、遗忘回顾mongoDB默认不需要使用账号密码即可访问数据库.下面是给mongoDB添加超级管理员和普通用户的方法 以系统管理员的方式运行powershell连接数据库 mongo查看数据库: show dbs切换到admin数据库: use admin创建超级管理员账户: db.createUser({user: roo…

Win10安装MySQL5.7.22 解压缩版(手动配置)方法

1.下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/5.7.html#downloads 直接点击下载项 下载后&#xff1a; 2.可以把解压的内容随便放到一个目录&#xff0c;我的是如下目录&#xff08;放到C盘的话&#xff0c;可能在修改ini文件时涉及权限问题&#xff0c;之后我…

Elemant-UI日期范围的表单验证

Form 组件提供了表单验证的功能&#xff0c;只需要通过 rules 属性传入约定的验证规则&#xff0c;并将 Form-Item 的 prop 属性设置为需校验的字段名即可。但是官网的示例只有普通日期类型的验证&#xff0c;没有时间范围的验证。 一开始&#xff0c;我认为时间时间范围的是一…

node --- [express项目] 开发环境下使用morgan控制台输出访问信息

说明 源代码记录、遗忘回顾 process.env node中提供了一个process.env接口用于访问计算机中的系统环境变量. 可以利用以上属性来区分当前的环境是开发环境还是生产环境,代码如下: if (process.env.NODE_ENV development) {console.log(当前环境是开发环境) } else {consol…

Dynamics CRM 访问团队的使用

访问团队和负责人团队的区别是&#xff1a;负责人团队可以拥有记录&#xff0c;访问团队不能拥有记录也不能加入解决方案中。 访问团队用法1&#xff1a;可以将不同组织的人员加入到访问组实现数据的更新、删除、共享 访问团队用法2&#xff1a;访问团队模板的使用 步骤一&…

业务逻辑

快捷支付接口规范 问题背景 持卡人身份验证持卡人在发卡银行提供的身份验证服务器进行验证&#xff0c;将结果告知商户资金清算资金清算在身份验证通过后进行即时清算&#xff0c;也可能是通过专用资金清算网络进行传统方法弊端 持卡人需要访问很多网站才能完成一次完整支付 &a…

node --- [express] cookie/session 机制与 中间件的使用(路由守卫)

说明 源代码记忆、遗忘回顾使用 cookie/session 机制,让 客户端/服务器 的访问变得有状态 cookie 与 session 由于 HTTP 协议的无状态性,当一次连接断开后. 服务器并不会记录用户是否登录. 因此需要引入 cookie/session 机制 cookie cookie: 浏览器在电脑硬盘中开辟的一块空…

kprobe原理解析

参考 http://www.cnblogs.com/honpey/p/4575928.html kprobe是linux内核的一个重要特性&#xff0c;是一个轻量级的内核调试工具&#xff0c;同时它又是其他一些更高级的内核调试工具&#xff08;比如perf和systemtap&#xff09;的“基础设施”&#xff0c;4.0版本的内核中&a…

02 数据类型

转载于:https://www.cnblogs.com/theoup/p/9875293.html