理解JavaScript原型prototype

一张图理解JS的原型(prototype、_proto_、constructor的三角关系) 注意:前方高能预警,请认真仔细看完,阅读完后自己再次画下原型图,相信你一定会有更深刻的认识。(推荐炒鸡好用的画流程图的软件ProcessOn) 构造函数:function Foo ( ) { }; 实例对象:let f1=new Foo;                  let o1=new Foo; 每个函数都有 prototype 属性,除了 Function.prototype.b... 阅读详情

注:本文来自微博网友@三月沙 的翻译投稿。

Javascript原型总会给人产生一些困惑,无论是经验丰富的专家,还是作者自己也时常表现出对这个概念某些有限的理解,我认为这样的困惑在我们一开始接触原型时就已经产生了,它们常常和new、constructor相关,特别是函数(function)的原型(prototype)属性(property)。事实上,原型是一种非常简单的概念。为了更好的理解它,我们应该首先记住这个原则,那就是忘记我们已经学到的关于构造原型(construtor prototypes)的认识。

什么是原型?

原型是一个对象,其他对象可以通过它实现属性继承。

任何一个对象都可以成为原型么?

是

哪些对象有原型

所有的对象在默认的情况下都有一个原型,因为原型本身也是对象,所以每个原型自身又有一个原型(只有一种例外,默认的对象原型在原型链的顶端。更多关于原型链的将在后面介绍)

好吧,再绕回来,那什么又是对象呢?

在javascript中,一个对象就是任何无序键值对的集合,如果它不是一个主数据类型(undefined,null,boolean,number,or string),那它就是一个对象

你说每个对象都有一个原型,可是我当我写成({}).prototype 我得到了一个null,你说的不对吧?

忘记你已经学到的关于原型属性的一切,它可能就是你对原型困惑的根源所在。一个对象的真正原型是被对象内部的[[Prototype]]属性(property)所持有。ECMA引入了标准对象原型访问器Object.getPrototype(object),到目前为止只有Firefox和chrome实现了此访问器。除了IE,其他的浏览器支持非标准的访问器__proto__,如果这两者都不起作用的,我们需要从对象的构造函数中找到的它原型属性。下面的代码展示了获取对象原型的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
var a = {};
 
  //Firefox 3.6 and Chrome 5
 
  Object.getPrototypeOf(a); //[object Object]  
 
  //Firefox 3.6, Chrome 5 and Safari 4
 
a.__proto__; //[object Object]  
 
  //all browsers
 
  a.constructor.prototype; //[object Object]

ok,一切都进行的很好,但是false明明是一个主数据类型,可是false.__proto__却返回了一个值

当你试图获取一个主数据类型的原型时,它被强制转化成了一个对象

1
2
3
//(works in IE too, but only by accident)
 
false .__proto__ === Boolean( false ).__proto__; //true

我想在继承中使用原型,那我该怎么做?

如果仅仅只是因为一个实例而使用原型是没有多大意义的,这和直接添加属性到这个实例是一样的,假如我们已经创建了一个实例对象 ,我们想要继承一个已经存在的对象的功能比如说Array,我们可以像下面这样做( 在支持__proto__ 的浏览器中)

 

1
2
3
4
//unusual case and does not work in IE
var a = {};
a.__proto__ = Array.prototype;
a.length; //0

———————————————————————————————————–
 译者注:上面这个例子中,首先创建了一个对象a,然后通过a的原型来达到继承Array 这个已经存在的对象的功能
———————————————————————————————————–

原型真正魅力体现在多个实例共用一个通用原型的时候。原型对象(注:也就是某个对象的原型所引用的对象)的属性一旦定义,就可以被多个引用它的实例所继承(注:即这些实例对象的原型所指向的就是这个原型对象),这种操作在性能和维护方面其意义是不言自明的

这也是构造函数的存在的原因么?

是的。构造函数提供了一种方便的跨浏览器机制,这种机制允许在创建实例时为实例提供一个通用的原型

在你能够提供一个例子之前,我需要知道constructor.prototype 属性究竟是什么?

首先,javascript并没有在构造函数(constructor)和其他函数之间做区分,所以说每个函数都有一个原型属性。反过来,如果不是函数,将不会有这样一个属性。请看下面的代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//function will never be a constructor but it has a prototype property anyway
 
Math.max.prototype; //[object Object]
 
//function intended to be a constructor has a prototype too
 
var A = function (name) {
 
      this .name = name;
 
}
 
  A.prototype; //[object Object]   
 
  //Math is not a function so no prototype property
 
  Math.prototype; //null

现在我们可以下个定义了:函数A的原型属性(prototype property )是一个对象,当这个函数被用作构造函数来创建实例时,该函数的原型属性将被作为原型赋值给所有对象实例(注:即所有实例的原型引用的是函数的原型属性)
———————————————————————————————————-
译者注:以下的代码更详细的说明这一切

//创建一个函数b
var b = function(){ var one; }
//使用b创建一个对象实例c
var c = new b();
//查看b 和c的构造函数
b.constructor;   // function Function() { [native code]}
b.constructor==Function.constructor;  //true
c.constructor;  //实例c的构造函数 即 b function(){ var one; }
c.constructor==b  //true

//b是一个函数,查看b的原型如下
b.constructor.prototype // function (){}
b.__proto__  //function (){}

//b是一个函数,由于javascript没有在构造函数constructor和函数function之间做区分,所以函数像constructor一样,
//
有一个原型属性,这和函数的原型(b.__proto__ 或者b.construtor.prototype)是不一样的
b.prototype //[object Object]   函数b的原型属性

b.prototype==b.constructor.prototype //fasle
b.prototype==b.__proto__  //false
b.__proto__==b.constructor.prototype //true

//c是一个由b创建的对象实例,查看c的原型如下
c.constructor.prototype //[object Object] 这是对象的原型
c.__proto__ //[object Object] 这是对象的原型

c.constructor.prototype==b.constructor.prototype;   //false  c的原型和b的原型比较
c.constructor.prototype==b.prototype;   //true c的原型和b的原型属性比较

//为函数b的原型属性添加一个属性max
b.prototype.max = 3
//实例c也有了一个属性max
c.max   //3
上面的例子中,对象实例c的原型和函数的b的原型属性是一样的,如果改变b的原型属性,则对象实例c
的原型也会改变

———————————————————————————————————-

理解一个函数的原型属性(function’s prototype property )其实和实际的原型(prototype)没有关系对我们来说至关重要

1
2
3
4
5
6
7
8
9
10
11
//(example fails in IE)
 
  var A = function (name) {
 
   this .name = name;
 
}
 
A.prototype == A.__proto__; //false
 
  A.__proto__ == Function.prototype; //true - A's prototype is set to its constructor's prototype property

给个例子撒

你可能曾经上百次的像这样使用javascript,现在当你再次看到这样的代码的时候,你或许会有不同的理解。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Constructor. <em>this</em> is returned as new object and its internal [[prototype]] property will be set to the constructor's default prototype property
var Circle = function (radius) {
     this .radius = radius;
     //next line is implicit, added for illustration only
     //this.__proto__ = Circle.prototype;
  }    
//augment Circle's default prototype property thereby augmenting the prototype of each generated instance
Circle.prototype.area = function () {
     return Math.PI* this .radius* this .radius;
  }   
  //create two instances of a circle and make each leverage the common prototype
var a = new Circle(3), b = new Circle(4);
  a.area().toFixed(2); //28.27
  b.area().toFixed(2); //50.27

棒极了。如果我更改了构造函数的原型,是否意味着已经存在的该构造函数的实例将获得构造函数的最新版本?

不一定。如果修改的是原型属性,那么这样的改变将会发生。因为在a实际被创建之后,a.__proto__是一个对A.prototype 的一个引用,。

1
2
3
4
5
6
7
var A = function (name) {
     this .name = name;
  }   
var a = new A( 'alpha' );
a.name; //'alpha'   
  A.prototype.x = 23;   
a.x; //23

——————————————————————————————————
译者注:这个和上例中的一样,实例对象a的原型(a.__proto__)是对函数A的原型属性(A.prototype)的引用,所以如果修改的是A的原型属性,

改变将影响由A创建的对象实例a 在下面的例子中,但是对函数A的原型进行了修改,但是并没有反应到A所创建的实例a中

var A = function(name)
{
this.name = name;
}
var a = new A(‘alpha’);
a.name; //’alpha’

A.__proto__.max = 19880716;

a.max   //undefined

——————————————————————————————————

但是如果我现在替换A的原型属性为一个新的对象,实例对象的原型a.__proto__却仍然引用着原来它被创建时A的原型属性

1
2
3
4
5
6
7
var A = function (name) {
     this .name = name;
}  
  var a = new A( 'alpha' );
a.name; //'alpha'   
  A.prototype = {x:23};    
  a.x; //null

——————————————————————————————————————
译者注:即如果在实例被创建之后,改变了函数的原型属性所指向的对象,也就是改变了创建实例时实例原型所指向的对象

但是这并不会影响已经创建的实例的原型。
——————————————————————————————————————-

一个默认的原型是什么样子的?

1
2
3
4
var A = function () {};
  A.prototype.constructor == A; //true
  var a = new A();
  a.constructor == A; //true (a's constructor property inherited from it's prototype)

instance of 和原型有什么关系

如果a的原型属于A的原型链,表达式 a instance of A 值为true。这意味着 我们可以对instance of 耍个诡计让它不在起作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var A = function () {}   
 
  var a = new A();
 
  a.__proto__ == A.prototype; //true - so instanceof A will return true
 
  a instanceof A; //true;   
 
//mess around with a's prototype
 
  a.__proto__ = Function.prototype;
 
  //a's prototype no longer in same prototype chain as A's prototype property
 
  a instanceof A; //false

还能使用原型做些什么呢?

记住我曾经所提到过的每个构造函数都有一个原型属性,它用来为每一个它所创建的实例提供原型。这同样也适用原生态的构造函数Function,String等,扩展这个属性,我们可以达到扩展指定构造函数的所有实例
我曾经在之前的很多文章中使用过这个技巧来演示函数的拓展。在tracer utility 这篇文章中所有的string实例都实现了times这个方法,对字符串本身进行指定数目的复制

1
2
3
4
5
6
7
String.prototype.times = function (count) {
     return count < 1 ? '' : new Array(count + 1).join( this );
  }
 
"hello!" .times(3); //"hello!hello!hello!";
 
"please..." .times(6); //"please...please...please...please...please...please..."

告诉我继承是怎样通过原型来工作的。什么是原型链?

因为每个对象和原型都有一个原型(注:原型也是一个对象),对象的原型指向对象的父,而父的原型又指向父的父,我们把这种通过原型层层连接起来的关系撑为原型链。这条链的末端一般总是默认的对象原型。

1
2
3
4
5
6
7
a.__proto__ = b;
 
  b.__proto__ = c;
 
  c.__proto__ = {}; //default object
 
{}.__proto__.__proto__; //null

原型的继承机制是发生在内部且是隐式的.当想要获得一个对象a的属性foo的值,javascript会在原型链中查找foo的存在,如果找到则返回foo的值,否则undefined被返回。

赋值呢?

原型的继承 is not a player 当属性值被设置成a.foo=’bar’是直接给a的属性foo设置了一个值bar。为了把一个属性添加到原型中,你需要直接指定该原型。

以上就是这篇文章所要讲述的。我个人感觉自己对原型概念的理解还是比较深刻的,但我的观点并不能代表一切。如有纰漏和异议,敬请告知。

我在哪里还能获得关于原型更多的信息?

我推荐这篇由Dmitry A. Soshnikov所著的文章,非常优秀。

 

英文原文:http://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/


将一维数据(序列)转化为二维数据(图像)的方法汇总GAFS, MTF, Recurrence plot,STFT 虽然深度学习方法(1D CNN, RNN, LSTM 等)可以直接处理一维数据,但是当前的深度学习方法主要还是处理二维结构数据的,特别是在计算机视觉CV以及自然语言处理NLP领域,各种各样的方法层出不穷。因此,如果能够将一维序列数据转化为二维(图像)数据, 则可以直接结合CV以及NLP领域的方法,是不是很有趣! GAF, GASF, GADF, MTF, Recurrence Plot, STFT, 短时傅里叶变换 阅读详情

相关推荐

Python自动化生成HyperMesh Tcl命令流:从几何建模到有限元分析

本文详细介绍了如何利用Python自动化生成HyperMesh的Tcl命令流,实现从几何建模到有限元分析的全流程二次开发。通过封装常用操作函数,工程师可以高效完成参数化建模、自动网格划分及求解器文件输出,显著提升CAE前处理效率与标准化水平。

weixin_29041767的博客 424

JavaScript 原型

理解JavaScript原型 发布时间:2011-12-10 17:00 来源:伯乐在线 分类: 程序员 都等你发言 :) 分享到: &lt;!-- div id="sharebutton"&gt;&lt;/div --&gt; 文章 注:本文来自微博网友@三月沙 的翻译投稿。 Javascript的原型总会给人...

DeleiGuo-优快云 240

基于航天宏图PIE-SAR软件的高分三号(GF-3)SAR影像的预处理

软件官网 航天宏图—国内领先的卫星运营与应用服务提供商(官网) 一、数据导入 数据导入-GF-3-根据模式选择 参数文件导入解压后GF-3数据的XML文件 通道自动填充 设置输出目录 确定 等待,加载图像、自动构建金字塔 二、复数数据转换 强度/幅度特征是SAR影像最主要的特征之一,基于SAR强度/幅度影像可以提取地物目标信息,因此需要将SAR复数数据转换为SAR强度/幅度数据。导入输入影像,设置参数类型,输出目录、命名、类型; 漫长的等待 三、多视 为提...

weixin_52127098的博客 9003

详解Javascript中prototype属性

在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例。但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不是基于‘类的',而是通过构造函数(constructor)和原型链(prototype chains)实现的。但是在ES6中提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。

Roninwz的博客 1126

物联网技术(AIR780E cat1-4G模块+小程序+腾讯云MQTT)驱动的智能井盖系统设计(连载01)

终端设备采用AIR780E模块作为主控器,电子模块有三轴加速度传感器、可燃气体传感器,AIR780E模块(4G模块)通过MQTT通信协议进行数据打包上传至EMQX服务器,在EMQX服务器中,用户可以自行订阅主题和发布主题,小程序通过MQTT通信协议订阅EMQX服务器的主题,服务器通过接收到硬件发布的数据,转发到微信小程序。

leida_3669的博客 2218

ROS 2 Slam Toolbox实战:从零跑通2D激光建图

SLAM(同步定位与地图构建)是移动机器人实现自主导航的基础技术,其核心在于通过传感器数据实时估计位姿并构建环境栅格地图。slam_toolbox作为ROS 2 Humble及后续LTS版本官方主推的2D SLAM后端,采用图优化+闭环检测架构,兼顾实时性、鲁棒性与工程可维护性。相比cartographer和hector_slam,它原生支持ROS 2、参数精简、诊断友好,特别适合硬件资源有限、缺乏IMU或深度相机的差速机器人平台。本文聚焦真实部署场景,覆盖RPLIDAR等常见2D激光雷达与TurtleBo

weixin_30596165的博客 358

JavaScript之原型

介绍JavaScript原型,理解原型链以及原生继承的使用。

m0_56599554的博客 450

我每天如何使用 ChatGPT

我偶尔会用这个功能作为开始。我本人非常喜欢阅读,让 ChatGPT 来概括所有文章,感觉就像身处于但丁描述的地狱的某个层次那样痛苦。然而,有时一些文章实在是太啰嗦、无聊,或者写得让人不愉快(比如一个无趣记者对一个让人讨厌的人进行的漫无焦点的采访)。我需要获取这些文章中的一些信息,以便保持信息的更新和了解。在晚期资本主义的广告经济下,很多文章只在一个段落里提供新信息,其余都是无聊的填充内容,只是为了展示糟糕的广告,这实在是对人们的时间和生命的一种浪费。我有几次利用 ChatGPT 来。

KevinDai007的博客 3784

JavaScript 中的原型

1.函数定义时,就存在一个属性prototype,它的值是一个普通的Object对象,这就是原型; 2.对象都是由构造函数new出来的,构造函数是由Function() new出来的,Function是浏览器创建js引擎时就已经存在; 3.constructor,获取对象的构造函数(obj.constructor),这个属性存储在构造函数的原型中,对象会继承原型中的方法和属性 4.对象的隐式原型(obj.__proto__)指向创建该对象的构造函数的原型(),指向同一空间 ...

m0_58510118的博客 2300

Flow Matching03-01:微分方程【微分方程(描述变化规律的方程):包含未知函数和它的导数的方程】【公式解(精确)、数值解(逼近)】

好的,我将从数学角度详细解释Flow Matching,从高中生能理解的基础知识开始,逐步深入到高级概念。

u013250861的博客 219

【STM32系统】基于STM32+手机APP设计的智能停车场系统

功能简介1、进出停车场时需要刷卡,进行一个记时、计费的功能。2、停车位配有超声波检测,主要识别车位是否被占用。3、车位区域配有OLED显示屏,用户可以通过显示屏看到空闲车位。4、车位配有车位灯。当用户找不到车位可以通过手机点亮车位灯5、停车场配有温湿度检测和烟雾检测模块。当环境发生异常状态。会触动紧急报警。6、停车场信息会通过Wi-Fi发送数据上传至阿里云。用户可以通过手机了解到停车场空闲车位和停车时间、费用。

嵌入式阿齐Archie 2万+

JavaScript_原型

JavaScript 是一种基于原型的脚本语言,它通过原型可以实现一种伪继承。

qq_39756007的博客 444

华为od 面试八股文_前端_01_含答案

华为od 面试八股文_前端_01_含答案

MISAYAONE的博客 2748

javascript-js 的prototype原型理解讲解

起初接触到这个prototype我是拒绝的,我还是花了一部分时间来理解这个东西,算不上精通,有什么问题回复在下面毕竟我是板砖挨惯了(滑稽);在我理解看来,prototype不外乎就两个基础的作用: 1.动态的添加类的属性和方法 2.复制原类的内容我们先来看第一个: 首先来定义一个简单的Person类;var Person = function(name,age){ //指定该类的属性为

小辣抓 905

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Statistics and Machine Learning Toolbox

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

JavaScript 原型与原型链:深入理解 __proto__ 和 prototype 的由来与关系

JavaScript 没有类,而是通过构造函数和原型模拟类的行为。prototype是函数特有的属性,用于定义共享的属性和方法。__proto__是对象特有的属性,用于构建原型链。原型链是 JavaScript 实现继承的机制,通过__proto__向上查找属性和方法。new关键字通过构造函数创建对象,并建立原型链关系。理解原型和原型链是掌握 JavaScript 面向对象编程的关键。虽然 ES6 引入了class语法,但其底层仍然是基于原型的实现。

小白的博客 810

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

js中的原型prototype的理解+实例

js中的原型prototype的理解+实例

Azbtt的博客 1042

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

js中prototype原型的理解

函数的prototype原型的理解 prototype两个基础的作用: 1.动态的添加类的属性和方法 2.复制原类的内容 我们先来看第一个: 首先来定义一个简单的Person类; var Person = function(name,age){ //指定该类的属性为参数值 this.name = name; this.age = age; //为该类指定一个talk方法 this.talk = f...

weixin_46439533的博客 145

关于JavaScript的Prototype及原型对象的理解

prototype,原型对象是学习javascript的基础。了解prototype,运用原型对象可以写出更好的面向对象设计的代码

long的博客 2164

js 之 prototype原型 理解

原型在js中,是一个相对而言较难理解易混淆的概念,这里特对原型做了一个小总结,是参照《JavaScript 高等程序设计》(第三版)做的一些总结提取。 1、在js中,创建一个函数的同时,就会根据一组特定规则为该函数创建一个 prototype 属性,这个属性是一个指针,指向函数的原型对象。      在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数) 属性,这个属

维生素宿舍的博客 432

js 为什么把方法写在原型上_理解JS的prototype

刚开始写前端那会儿,一直不太理解js的prototype。现在对js理解深入之后,来谈一谈prototype。prototype是什么JavaScript在设计之初,是作为一种网页脚本语言,没有设计得很复杂,这种语言只要能够完成一些简单操作就够了。Javascript里面所有的数据类型都是对象(object)。在ES6之前,js中是没有Class的概念的(ES6中的类也是语法糖,本质还是基于原型)...

weixin_32049849的博客 1956

帮你轻松理解js原型链,__proto__,prototype,constructor

以下是总结一下,网上太多画图的,说明的,弯弯绕绕,云里雾里,很难让人简单理解,这里对一些常见的名词【换个说法】,可能好理解一点 理解下面几点,对于理解js的原型链,__proto__,prototype,constructor有帮助: js里,函数是对象,函数可以赋值给变量,也可以当参数传递 区分【定义对象】与【实例对象】 1.【定义对象】是function Person{} 这样的定义,Per...

老专家的博客 521

从__proto__和prototype来深入理解JS原型链

简介 首先继承作为JS面向对象编程核心之一,到底是什么东东呢?在我的理解中,从广义上来讲,就是让子类能有父类的属性和方法,从而父类就一处定义,多处复用,从狭义上来讲,就是玩原型链的,也就是说如果大家掌握了原型链,也就掌握了继承,接下来呢,我会从两部分给大家做个分享,分别是 原型链 实现继承 原型链 在说原型链之前,我先说下__proto__和prototype这两个属性,因为接下来,这两个词会经常出现 __proto__,用来读取或设置当前对象的原型对象(prototype),并且每个JS对象一定对应

麻瓜哇哇哇的博客 426

深入理解JavaScript之prototype原型以及原型链

什么是原型? 函数一旦创建就有一个prototype属性,该属性指向一个对象,该对象就是prototype对象,即原型对象。 总结:原型就是一个对象,即prototype对象。 原型的作用是:共享方法 构造函数在实例化对象的时候,每创建一个实例对象就会开辟空间存放构造函数中的属性和方法,如下: var Person = function(name,age){ this.name = name;...

邹呦呦_ 273

JavaScript原型prototype的理解

1. 每个函数(如Animal)都有一个prototype属性,其prototype属性指向该函数的原型对象(Animal Prototype)。 2. 原型对象都有一个constructor属性,其constructor属性指向构造函数(function Animal)。 3. 构造函数的实例对象(如cat)都有一个__proto__属性,其__proto__属性指向构造函数的原型对象,即Animal Prototype。

lseap的博客 265
上一篇: 深入学习JavaScript: apply 方法 详解(转)——非常好
下一篇: Django在网页中调用python小程序
Vivian_Chang
博客等级 码龄14年 2粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值