


以问题开始:
function Base(){}var base = new Base()
上面两行代码会创建几个对象(object)?
要回答这个问题,先明确一下Javascript里object的概念。
Objects
在Javascript里,几乎一切都是object(Arrays、Functions、Numbers、Objects……),而没有C#里的class的概念。object的本质是一个name-value pairs的集合,其中name是string类型的,可以把它叫做“property”,value包括各种objects(string,number,boolean,array,function…),指的是property的值。
typeof
既然object包含Arrays、Functions、Numbers、Objects……,那怎么区分这些呢?答案是typeof。 typeof返回一个字符串,如typeof(Null) = “object”,typeof(false) = “Boolean”, typeof(1) = “number”。既然总是返回字符串,那么对于typeof (typeof x),不管x是什么,总是返回”string”。
Constructor
JS里没有class,也就没有class里的构造函数,那么object是怎么被创建的呢?用构造器:constructor。constructor其实就是Function,因此本身也是object。开头的function Base(){}就是一个构造器,var b = new Base()就是用这个构造器(通过关键字new)创建了一个叫b的object。至此我们可以得出结论,开头的两行代码至少创建了2个object:一个是Base,类型为function的object,一个是base,类型为object的object。
Function()和Object()
这是两个重要的预定义好的构造器。一切function(比如开头的Base())都是由Function()构造出来的;而Object的prototype将会被所有object继承,下面会讲到。
Function的创建过程
当执行function Base(){this.a = 1}时,相当于var Base = new Function(“this.a = 1”),也就是说,这行代码本身,将使用预定义好的Function() constructor,来构造一个function型object(即Base)出来。在这个创建过程中,js将做哪些事呢?
1, 首先当然会创建一个object起来,Base指向这个object。typeof 这个object = “function”
2, 给Base附上__proto__属性,让它等于Function这个构造器的prototype(也是预定义好的)。这是很重要的一步,也是规律性的一步。(规律:)在执行任意类似varx = new X()时,都会把X的prototype赋给x的__proto__,也就是说,x.__proto__和X.prototype此时会指向同一个对象。
3, 为Base创建call属性,该属性是个function。因此我们可以这样写:Base.Call()
4, 为Base创建Construct属性,该属性也是个function。在执行var base = new Base()时,即会调用这个Construct属性。
5, 为Base创建Scope,Length等属性,略。
6, 为Base创建prototype属性:先用new Object()创建一个对象,为这个对象创建一个属性叫constructor,该属性值设置为Base。再把Base的prototype设置为这个新创建的对象。伪代码如下:
<div> <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> x </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Object();<br>x.constructor </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Base;<br>Base.prototype </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> x;</span> </div>
先把关注点放到2和6。
__proto__和prototype
从2可以看出来,任意一个用构造器构造出来的object(包括Objects和Functions),都会有__proto__属性,指向该构造器的prototype属性。注意__proto__是个私有属性,在IE上是看不到的,我用的是chrome,可以看到。
从6可以看出,任意一个用new Function()构造出来的functions,都会有prototype属性,该属性是用new Object()构建出来的,初始公开属性只有一个constructor。
原型链
再来分析下第6步的伪代码,也就是为function创建prototype的这一步:
<div> <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> x </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Object(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 参见2中的规律,会有x.__proto__= Object.prototype。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">x.constructor </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Base;<br>Base.prototype </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> x;</span> </div>
此时我们用Base()构造一个对象出来:
<div> <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> base</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Base(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 参见2中的规律,会有base.__proto__ = Base.prototype,也就是 = x。</span> </div><div> <span style="COLOR: #008000"> </span><span style="COLOR: #008000; FONT-FAMILY: 'Courier New'"> // 因此有base.__proto__.__proto__ = x.__proto__</span> </div><div><span style="COLOR: #008000; FONT-FAMILY: 'Courier New'"> // 而x.__proto__ = Object.prototype(见上一个代码片段) </span></div><div><span style="COLOR: #008000; FONT-FAMILY: 'Courier New'"> // 所以,base.__proto__.__proto__ = Object.prototype.</span></div>
__proto__.__proto__,这就是传说中JS对象的原型链!由于用Function()创建构造器时的关键的第6步,保证了所有object的原型链的顶端,最终都指向了Object.prototype。
Property Lookup
而我们如果要读某个object的某个属性,JS会怎么做呢?
比如有个object叫xxx,我们执行alert(xxx.a),也就是读取xxx的a属性,那么JS首先会到xxx本身去找a属性,如果没找到,则到xxx.__proto__里去找a属性,由此沿着原型链往上,找到即返回(没找到,则返回undefined)。可以来看个例子:
上图得知:base本身是没有constructor属性的,但是base.constructor确实能返回Base这个函数,原因就在于base.__proto__有这个属性。(base.__proto__是啥?就是Base.prototype,上面构建Function的第6步的伪代码里,为Base.prototype.constructor赋值为Base本身。)
Object作为“基类”
另外,由于任意object的原型链的顶端都是Object.prototype。所以,Object.prototype里定义的属性,就会通过原型链,被所有的object继承下来。这样,预定义好的Object,就成了所有对象的“基类”。这就是原型链的继承。
看上图,Object.prototype已经预定义好了一些属性,我们再追加一条属性叫propertyA,那么这个属性和预定义属性一样,都可以从base上读到。
原型继承
已经得知,
对于 var xxx =new Object(); 有xxx.__proto__= Object.prototype;
对于 var xxx =new Base(); 有xxx.__proto__.__proto__= Object.prototype;
看上去很像什么呢?从c#角度看,很像Base是Object的子类,也就是说,由Base()构造出来的object,比由Object()构造出来的object,在原型链上更低一个层级。这是通过把Base.prototype指向由Object()创建的对象来做到的。那么自然而然,如果我想定义一个继承自Base的构造器,只需把改构造器的prototype指向一个Base()构造出来的对象。
<div> <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000"> Derived(){}<br></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> base </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Base();<br>Derived.prototype </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> base;<br></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> d </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> newDerived(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">很容易推算出:d.__proto__.__proto__.__proto__ = Object.prototype.</span> </div>
推算过程:d.__proto__指向Derived.prototype,也就是base;则__proto__.__proto__指向base.__proto__,也就是Base.prototype,也就是某个new object()创建出来的东东,假设是o;则__proto__.__proto__.__proto__指向o.__proto__,也就是Object.prototype。
回答开头的问题,以及几个新的问题
那两行代码至少创建了三个对象:Base、base、Base.prototype。顺便说说,base是没有prototype属性的,只有function类型的object,在被构建时才会被创建prototype属性。
d.constructor会返回什么呢?
构造器Base()和Derived()里都是空的,如果有代码,将会怎么被执行呢?
……
待续。见下篇

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,已经成为Web应用程序之间数据交换的常用格式。PHP的json_encode()函数可以将数组或对象转换为JSON字符串。本文将介绍如何使用PHP的json_encode()函数,包括语法、参数、返回值以及具体的示例。语法json_encode()函数的语法如下:st

楔子我们知道对象被创建,主要有两种方式,一种是通过Python/CAPI,另一种是通过调用类型对象。对于内置类型的实例对象而言,这两种方式都是支持的,比如列表,我们即可以通过[]创建,也可以通过list(),前者是Python/CAPI,后者是调用类型对象。但对于自定义类的实例对象而言,我们只能通过调用类型对象的方式来创建。而一个对象如果可以被调用,那么这个对象就是callable,否则就不是callable。而决定一个对象是不是callable,就取决于其对应的类型对象中是否定义了某个方法。如

使用Python的__contains__()函数定义对象的包含操作Python是一种简洁而强大的编程语言,提供了许多强大的功能来处理各种类型的数据。其中之一是通过定义__contains__()函数来实现对象的包含操作。本文将介绍如何使用__contains__()函数来定义对象的包含操作,并且给出一些示例代码。__contains__()函数是Pytho

标题:使用Python的__le__()函数定义两个对象的小于等于比较在Python中,我们可以通过使用特殊方法来定义对象之间的比较操作。其中之一就是__le__()函数,它用于定义小于等于比较。__le__()函数是Python中的一个魔法方法,并且是一种用于实现“小于等于”操作的特殊函数。当我们使用小于等于运算符(<=)比较两个对象时,Python

Javascript对象如何循环遍历?下面本篇文章给大家详细介绍5种JS对象遍历方法,并浅显对比一下这5种方法,希望对大家有所帮助!

Python中如何使用getattr()函数获取对象的属性值在Python编程中,我们经常会遇到需要获取对象属性值的情况。Python提供了一个内置函数getattr()来帮助我们实现这个目标。getattr()函数允许我们通过传递对象和属性名称作为参数来获取该对象的属性值。本文将详细介绍getattr()函数的用法,并提供实际的代码示例,以便更好地理解。g

使用Python的isinstance()函数判断对象是否属于某个类在Python中,我们经常需要判断一个对象是否属于某个特定的类。为了方便地进行类别判断,Python提供了一个内置函数isinstance()。本文将介绍isinstance()函数的用法,并提供代码示例。isinstance()函数可以判断一个对象是否属于指定的类或类的派生类。它的语法如下

Python中如何使用__add__()函数定义两个对象的加法运算在Python中,可以通过重载运算符来为自定义的对象添加对应的运算功能。__add__()函数是用于定义两个对象的加法运算的特殊方法之一。在本文中,我们将学习如何使用__add__()函数来实现对象的加法运算。在Python中,可以通过定义一个类来创建自定义的对象。假设我们有一个叫做"Vect


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

WebStorm Mac version
Useful JavaScript development tools

Zend Studio 13.0.1
Powerful PHP integrated development environment

SublimeText3 Linux new version
SublimeText3 Linux latest version

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.
