prototype的本质

__proto__与prototype __proto__与prototype的区别 阅读详情
在《关于思维方式的思绪》那篇文章里提到了,
原型的本质就是一种 委托关系 。
即我这里没有,就到我的原型里去看看,一旦找到就当成我的用。

本文详细说一下这个事情。
比如某女买东西,钱都是她老公付款的。
用程序刻画是这样的:

   
1
2
3
4
5
6
7
8
9
10
11
var  girl  =  {
     name :  '小美'
} ;
var  boy  =  {
     name :  '小帅' ,
     pay :  function ( )  {
         console . log ( '花了一千元' ) ;
     }
} ;
Object . setPrototypeOf ( girl ,  boy ) ;
girl . pay ( ) ;

程序中指明了girl的原型是boy,girl没pay方法,但是boy有,所以boy花钱了。
从这个例子来看那么,原型是一种委托关系,如果说是一种继承关系就不是那么贴切。
因为这段代码更等价于如下的代码:

   
1
2
3
4
5
6
7
8
9
10
11
12
13
var  girl  =  {
     name :  '小美' ,
     pay :  function ( )  {
         boy . pay ( ) ;
     }
} ;
var  boy  =  {
     name :  '小帅' ,
     pay :  function ( )  {
         console . log ( '花了一千元' ) ;
     }
} ;
girl . pay ( ) ;

用这种委托关系,而不是继承关系去理解原型,会感觉一切豁然开朗。
我们通过下面这个例子来看看什么是原型链?

   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var  a  =  {
     fn1 :  function ( )  {
         console . log ( 1 ) ;
     }
} ;
var  b  =  {
     fn2 :  function ( )  {
         console . log ( 2 ) ;
     }
} ;
var  c  =  {
     fn3 :  function ( )  {
         console . log ( 3 ) ;
     }
} ;
var  d  =  {
     fn4 :  function ( )  {
         console . log ( 4 ) ;
     }
} ;
Object . setPrototypeOf ( d ,  c ) ;
Object . setPrototypeOf ( c ,  b ) ;
Object . setPrototypeOf ( b ,  a ) ;
d . fn1 ( ) ;
d . fn2 ( ) ;
d . fn3 ( ) ;
d . fn4 ( ) ;

上面的代码中,a是b的原型,b是c的原型,c又是d的原型。
那么d要找fn1方法,怎么找呢?
先去其原型c中找,没找到,
再去c的原型b中找,也没找到,
再去b的原型a中去找,找到了,
因此能调用fn1方法。
上面的过程就是原型链查找的过程。

讲到这里,原型链的原理想必是懂了。
此时我们再来看a,b,c,d四个对象是什么关系。
如果要看做是继承的话,那么就是父子关系。
如果用委托观点来看,那么每一个对象,都是后一个对象的智囊,也就是原型。
所以本文的观点是什么呢?
不要把原型当成亲爹,要当成智囊,要当成老公,要当成干爹,
本质是委托关系,说白了,就是“利用”。


其实讲到这儿原型是什么基本已经说完,后面我准备展开说说,跟构造函数扯上。

第一个问题,什么叫“一旦找到就当成我的用”?
其实指的是this问题。
比如:

   
1
2
3
4
5
6
7
8
9
10
var  a  =  {
     sayName :  function ( )  {
         alert ( this . name ) ;
     }
} ;
var  laoyao  =  {
     name :  'laoyao'
} ;
Object . setPrototypeOf ( laoyao ,  a ) ;
laoyao . sayName ( ) ;


第二个问题,克隆的观点?
假如一个对象是一个空对象的原型,
因为空对象什么也没有,所有的都来自其原型,
我们可以认为此对象是其原型的克隆。

   
1
2
3
4
5
6
7
8
9
10
var  laoyao  =  {
     name :  'laoyao' ,
     sayName :  function ( )  {
         alert ( this . name ) ;
     }
} ;
var  fenshen  =  { } ;
Object . setPrototypeOf ( fenshen ,  laoyao ) ;
console . log ( fenshen . name ) ;
fenshen . sayName ( ) ;

当然,Object.create更适合描述克隆。

   
1
2
3
4
5
6
7
8
9
var  laoyao  =  {
     name :  'laoyao' ,
     sayName :  function ( )  {
         alert ( this . name ) ;
     }
} ;
var  fenshen  =  Object . create ( laoyao ) ;
console . log ( fenshen . name ) ;
fenshen . sayName ( ) ;

这里只使用了create的第一个参数,对此,这段代码很其上一段代码没什么区别。

第三,我们封装产生对象的过程?
我们希望上述的那个laoyao对象能通过函数产生。比如我会这样做:

   
1
2
3
4
5
6
7
8
9
10
var  createPerson  =  function ( name )  {
     return  {
         name :  name ,
         sayName :  function ( )  {
              alert ( this . name )
         }
     } ;
}
var  laoyao  =  createPerson ( 'laoyao' ) ;
laoyao . sayName ( ) ;

我也换种方式来做:

   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var  createPerson  =  function ( name )  {
    
     var  o  =  { } ;
     o . name  =  name ;
    
     var  proto  =  {
         sayName :  function ( )  {
              alert ( this . name ) ;
         }
     } ;
    
     Object . setPrototypeOf ( o ,  proto ) ;
     return  o ;
}
var  laoyao  =  createPerson ( 'laoyao' ) ;
laoyao . sayName ( ) ;

我再继续变化,把proto拿出来

   
1
2
3
4
5
6
7
8
9
10
11
12
13
var  createPerson  =  function ( name )  {
     var  o  =  { } ;
     o . name  =  name ;
     Object . setPrototypeOf ( o ,  createPerson . proto ) ;
     return  o ;
}
createPerson . proto  =  {
     sayName :  function ( )  {
         alert ( this . name ) ;
     }
} ;
var  laoyao  =  createPerson ( 'laoyao' ) ;
laoyao . sayName ( ) ;

写到这里,你会发现其实跟我们平常写的代码很像:

   
1
2
3
4
5
6
7
8
9
10
var  Person  =  function ( name )  {
     this . name  =  name ;
}
Person . prototype  =  {
     sayName :  function ( )  {
         alert ( this . name ) ;
     }
} ;
var  laoyao  =  new  Person ( 'laoyao' ) ;
laoyao . sayName ( ) ;

我们来刻画一下这个new过程。
我们假设new是一个函数,类似call或bind的那样的函数
new Person('laoyao')
我们换成
Person.new('laoyao')
此函数定义如下:

   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Function . prototype . new  =   function ( )  {
     var  that  =  Object . create ( this . prototype ) ;
     this . apply ( that ,  arguments ) ;
     return  that ;
} ;
var  Person  =  function ( name )  {
     this . name  =  name ;
}
Person . prototype  =  {
     sayName :  function ( )  {
         alert ( this . name ) ;
     }
} ;
var  laoyao  =  Person . new ( 'laoyao' ) ;
laoyao . sayName ( ) ;

其中这new函数,不是完整模拟new的(考虑返回值是否是对象)。详细请看《js语言精粹》47页。其中this指向的是当前函数(Person)。
如果上面的代码看不习惯的话,我们也可以发明如下的api:
myNew(Person, 'laoyao')
完整示例代码如下:

   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var  myNew  =  function ( )  {
     var  Constructor  =  [ ] . shift . call ( arguments ) ;
     var  that  =  Object . create ( Constructor . prototype ) ;
     Constructor . apply ( that ,  arguments ) ;
     return  that ;
}
var  Person  =  function ( name )  {
     this . name  =  name ;
}
Person . prototype  =  {
     sayName :  function ( )  {
         alert ( this . name ) ;
     }
} ;
var  laoyao  =  myNew ( Person ,  'laoyao' ) ;
laoyao . sayName ( ) ;

上述代码改编于《JS设计模式与开发实践》第20页。

如果读者没有其他什么面向对象语言基础,
那么看此文,会觉得 new是一个封装委托关系的过程 。
而不是什么模拟java,模拟不彻底啥的。
所以在我看来,那些号召不要使用new的文章,也未必正确。

最后说下:这个委托的观点,《你不知道的javascript》有更详细的介绍。

也欢迎看本文的 《续》 。

本文完。

原文链接 http://www.qdfuns.com/notes/17398/35b250e9b392675c44f4f0cd833b72c8.html

GIS坐标系转换以及空间校正和地理配准 许多小伙伴都对坐标系,投影这类问题迷迷糊糊,我之前也一样,现在总结一下。 坐标系的转换1.为什么要进行坐标系的转换?2. 不同坐标系的介绍1.地理坐标系我国常见的地理坐标(1).北京54坐标系(2).西安80坐标系(3).WGS-84坐标系(4).大地2000坐标系2.投影坐标系我国常用的投影坐标系(1) UTM投影(2) 高斯-克吕格投影(3) 兰伯特投影(4) 阿尔伯斯投影投影坐标系的选择3. 坐标系的转换1.已知坐标系之间的转换1.1 两坐标系的参考椭球相同1.2 两坐标系的参考椭球不一致,但是GIS 阅读详情

相关推荐

Cisco Packet Tracert 无线路由器配置

Cisco Packet Tracert 无线路由器配置

yushan_caoyu的博客 2万+

javascript prototype本质

将一个对象设置为一个类型的原型,相当于通过实例化这个类型,为对象建立只读副本,在任何时候对副本进行改变,都不会影响到原来对象,而对原来对象进行改变,会影响到每一个副本,除非被改变的属性已经被副本自己的同名属性覆盖。用delete操作将对象自己的同名属性删除,则可以恢复原型属性的可见性。 原型属性修改的正确方法.html function ClassA(){ this

woshimaijunjinzhen的专栏 533

从零到一:手把手教你用STM32和WiFi打造智能温室大棚的物联网核心

本文详细介绍了如何利用STM32单片机和WiFi技术从零构建智能温室大棚的物联网核心系统。内容涵盖硬件选型、传感器集成、低功耗WiFi通信、自动控制逻辑及OLED显示,提供实际部署中的优化技巧和故障排查方案,帮助开发者打造稳定可靠的农业自动化解决方案。

c7d8e的博客 180

JavaScript的类型和对象

   JavaScript是基于对象的,任何元素都可以看成对象。然而,类型和对象是不同的。本文中,我们除了讨论类型和对象的一些特点之外,更重要的是研究如何写出好的并且利于重用的类型。毕竟,JavaScript这种流行的脚本语言如果能够进行良好的封装,并形成一个庞大的类型库,对于重用是非常有意义的。 网上对于prototype的文章很多,一直没明白核心的思想。最后写了很多例子代码后才明白:proto...

iteye_19319的博客 249

DC综合中set_dft_signal的实战配置与优化策略

本文深入解析了DC综合中set_dft_signal命令的实战配置与优化策略。文章从命令的核心作用出发,详细拆解了-view、-type、-usage等关键参数,并通过扫描使能与时钟门控的实战案例,展示了如何正确配置以实现测试模式下的功耗优化。同时,文章总结了高级优化策略、与低功耗流程的协同方法以及常见错误排查清单,旨在帮助数字芯片设计工程师构建高可测性、低功耗的稳健DFT基础。

weixin_28347369的博客 403

功率电感的设计步骤

学习视频原链接截图1截图2。

qq_32419593的博客 4887

Javascript Prototype本质总结

JavaScript是基于对象的,任何元素都可以看成对象。然而,类型和对象是不同的。本文中,我们除了讨论类型和对象的一些特点之外,更重要的是研究如何写出好的并且利于重用的类型。毕竟,JavaScript这种流行的脚本语言如果能够进行良好的封装,并形成一个庞大的类型库,对于重用是非常有意义的。 网上对于prototype的文章很多,一直没明白核心的思想。最后写了很多例子代码后才明白:pro...

华天下 122

【保姆级教程】YOLOv8_OBB旋转目标检测:训练自己的数据集

【保姆级教程】YOLOv8_OBB旋转目标检测:训练自己的数据集

m0_51579041的博客 1万+

prototype本质上还是一个JavaScript对象。 并且每个函数都有一个默认的prototype属性。

var Person=function(name) {  this.name = name;  }  Person.prototype = {  getName:function () {  return this.name; }  }  var zhang = new Person();  console.log(zhang.getName());

evilcry2012的专栏 1127

RTK_ROS_导航(4):接入move_base

现在我们要将之前的数据接入到Move_base中,使得机器人能够根据Map上的终点进行导航,并且实现避障效果如下图。

旋风小短腿 1947

大模型对齐的核心引擎:RLHF三阶段完整技术体系详解——从InstructGPT到ChatGPT与Claude 4.6的工程实践

RLHF从InstructGPT起步,经由ChatGPT、Claude系列的工程实践,已演变为现代大语言模型不可或缺的对齐基础设施。其三阶段流程——SFT构建基础能力基线,奖励模型将人类偏好编码为可微信号,PPO以KL约束驱动策略向偏好分布优化——构成了当代对齐技术的核心骨架。OpenAI的路线侧重于以海量人工标注和多目标奖励建模持续精细化RLHF流程,在规模与工程深度上持续推进;

nmdbbzcl的博客 1067

Sandboxie 日志体系完整指南:从消息代码到事件查看器一文读懂

Sandboxie(含 Sandboxie Plus 与 Classic)能把沙盒里每个程序的文件、注册表和网络操作都记下来,但它把这些信息拆成了三层:一份消息代码目录、一份写入 Windows 的运行时事件日志,以及一套面向翻译核对的覆盖报告。本指南带你把这三层一次性看懂,并学会自己定位、过滤和核对每一条 Sandboxie 日志输出。🔍 先讲你能拿到什么:看懂一条 `SBIE1101` 这

gitblog_00498的博客 198

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

简单理解js的prototype属性

在进入正文之前,我得先说说我认识js的prototype这个东西的曲折过程。   百度js的prototype的文章,先看看,W3School关于prototype的介绍:          你觉得这概念适合定义js的prototype这个东西吗?你是否也认为prototype是一个object对象的属性呢?是的话,请认真认真看我这篇文章,因为这篇文章会毁灭你的人生三观,呵

汪飞的博客 494

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

js中两种设置子类原型(prototype)来实现原型式继承的本质区别

Child.prototype = Object.create(Parent.prototype);与Child.prototype = new Parent(); 两种设置子类(Child)原型(prototype)的方法虽然都能实现继承的基本功能,但它们之间存在一些重要的区别和潜在的陷阱。

j15087159186的博客 601

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

JavaScript的prototype属性

今天写js代码的时候,看别的用prototype看的我云里雾里的,了解了一下: prototype 是函数的属性,它的本质是函数的原型对象 可以以此执行一下如下代码,体会一下。 <script> var ob = { };//超级简单的空对象 alert(JSON.stringify(ob.prototype)); function func(){ } alert(func.pro...

Sinclair 146

.__proto__和.prototype之间的一些区别

Object.prototype只是一个普通对象,它是js原型链的最顶端  Object.prototype.__proto__=== null;//true  Object.prototype.prototype === undefied;//true Object.prototype只是一个普通对象(普通对象没有prototype属性,所以值是undefined),Object.prototype是js原型链的最顶端, 它的__proto__是null(有__proto__属性,但值是null,..

hualidezhen的博客 397

JavaScript中prototype理解

我们知道JScript中对象的prototype属性,是用来返回对象类型原型的引用的。我们使用prototype属性提供对象的类的一组基本功能。并且对象的新实例会"继承"赋予该对象原型的操作。但是这个prototype到底是怎么实现和被管理的呢? 对于对象的prototype属

finding的专栏 6135

初识prototype

初识prototype          早就知道JavaScript有一个类似于C++的继承特性,也早就想领略一下它的强大。在我心里我认为js的完美程度不次于任何所知语言,他的强大在HTML5发布以后,水涨船高,地位也空前重要,在HTML5趋于引领整个互联网时代的进程中,它将发挥更大的作用。而继承是js的一个重要属性,你将在大部分网站看到prototype,包括移动Web的开发。    

smoehandboy的博客 294

ES5原型机制完全指南:prototype与constructor的底层原理

原型链是JavaScript中实现继承与属性共享的底层机制,而prototype和constructor则构成了理解这一机制的关键入口。在ES5中,每个函数都自动拥有一个prototype属性,它作为将来通过new创建的实例的内部原型引用;constructor则作为原型对象上的默认标签,反向指向创建它的构造函数。理解二者如何配合,不仅有助于厘清实例属性查找的完整路径,还能解释为何重写prototype会导致constructor漂移、旧实例不再属于该类等反直觉现象。在工程实践中,手写继承、类型判断、老代码

weixin_32576389的博客 255

通过复制生成实例的 Prototype模式

文章目录Prototype模式应用场景本质优点缺点角色Prototype模式的类图示例程序示例程序的类图示例代码拓展思路相关设计模式满足的原则 Prototype模式 应用场景 需要一个类的大量对象的时候,使用原型模式是最佳选择,因为原型模式是在内存中对这个对象进行拷贝,要比直接new这个对象性能要好很多,在这种情况下,需要的对象越多,原型模式体现出的优点越明显。 如果一个对象的初始化需要很多其他对象的数据准备或其他资源的繁琐计算,那么可以使用原型模式。 当需要一个对象的大量公共信息,少量字段进行个性化设

零碎@流年絮语 的博客 220
上一篇: 详解css3系列:动画@keyframes和Animation
下一篇: javascript用对象方法实现数组去重并排序
Young-杨
博客等级 码龄15年 56粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值