`
achun
  • 浏览: 311860 次
  • 性别: Icon_minigender_1
  • 来自: 河南郑州
社区版块
存档分类
最新评论

javascript的值,对象,原型

阅读更多

探讨一下,如有纰漏请指正.

认识在前面:先给出我们讨论的结果

===========================================

javascript是基于原型(prototype-based )的语言.

javascript具有面向对象(Object-Oriented )的编程风格.

变量不一定是对象(undefined,null等就是特例,但是NaN是个对象)

对象一定有值,也有成员(函数,属性)

Object不是顶级的,因为可以delete Object

顶级 的有:

Array Object
Boolean Object
Date Object
Function Object
Math Object
Number Object
RegExp Object
String Object

new 运算符具有一定的魔术性,这个说法我语言上还组织不好.

==========================================

首先我用了词:原型

马上您就知道为什么这么说了.

javascript是基于对象(Object-based )的吗?不是

javascript是面向对象(Object-Oriented )的吗? ,要清楚这句话指的是编程方法类似面向对象的编程,但是也有很多不同的地方.

那我们看看Mozilla官方的说法

写道
A prototype-based language, such as JavaScript, does not make this distinction: it simply has objects. A prototype-based language has the notion of a prototypical object, an object used as a template from which to get the initial properties for a new object. Any object can specify its own properties, either when you create it or at run time. In addition, any object can be associated as the prototype for another object, allowing the second object to share the first object's properties.

 javascript是基于原型(prototype-based )的语言.

 

那么我们在描述,研究这个语言的时候就会牵扯到这几个问题.

值和对象 :

var obj={};
var num=9;
var str='string'
var arr=[];

 很明显上面的几个变量都是一个对象,那变量一定是对象吗 ?

var foo;

 foo是一个变量,但是foo不是对象.对象有个事实上 的特征就是,对象一定有成员 (属性或方法).

 foo就没有任何成员,他的值是undefined ,而undefined 的定义是:

undefined is a property of the global object, i.e. it is a variable in global scope.
The initial value of undefined is the primitive value undefined.

undefined 属性是 Global 对象的一个成员,该属性在脚本引擎初始化后可用。如果已声明了一个变量但还没有初始化,那么该变量的值就是 undefined。

 也就是说undefined 是一个顶级共有属性,用关键字描述undefined 其实更确切.

 现在我们举几个值对象( javascript的其他类型的还有,就不提了)

'isstring'.constructor;//String()
true.constructor;//Boolean()
9.0.constructor;//Number();这下对了吧csf178
(9).constructor;//Number();匿名对象
9.constructor;//SyntaxError;经csf178指正,这是浮点数转换造成的语法冲突
[].constructor;//Array()
{}.constructor;//fireFox :SyntaxError;IE : Object();注意javascript定义中{}是代码块和对象定义,不是Operator
({}).constructor;//Object();匿名对象

 其实值对象这个说法不是很合适.就像上面的前3个确实是值.第4个(9)其实是一个匿名的Number对象 ,

但是接下来的两句就有意思了.{}和[]竟然还有如此的区别.而且fireFox和IE实现也不同.(其实从优先级上可以找到一些答案,可惜不同实现有差异)

Object Literals 中明确指出{}.xxx这种用法是错误的,所以fireFox出SyntaError是正常的.MS的jscript文档我没有看过,不知道如何解释这个.

那我们如何来评论javascript的这些特性呢?

抛弃面向对象这个说法吧,javascript真的不适合. javascript就是这样的不严格,但是很实用.

经csf178指正后,看来javascript仍旧是OO的.但是是prototype-based 的OO,不是Class-based的OO.

也就是说在javascript里所有的对象都有原型,官方给出的原型

(好在我写这个帖子的时候就是为了要搞清楚这3者的关系)

总结:变量不一定指向对象 (貌似废话),对象一定有值

原型 :

对象一定有原型constructor

这一点从可以从javascript的constructor的定义中找到根据.

请注意上面例子中所有的constructor都是以函数给出的,其实

原型constructor一定是一个函数形式的定义

javascript:function fun(){};
new fun.constructor;//anonymouse();
(new fun).constructor;//fun();
new fun().constructor;//fun();
(new fun()).constructor;//fun();

 为什么这样?其实这很正常,看看javascript运算符的优先级 就明白了.当然,你不能死照优先级来看语法的合法性,解释起来会很绕嘴的.

new Function().constructor;//Function()
new Function.constructor;//anonymous()
new (Function.constructor);//anonymous()
new (Function().constructor);//anonymous()

 这几个例子优先级就明显了.

(下面的几行是经csf178指正后,反思的结果)

回头再看看官方给出的原型 里面唯独却少了最重要的Object,我们知道Object一定是个对象(javascript里没有class),Object又不在Core里,那Object是从哪里来的呢?

Object().constructor;//Object()
Object.constructor;//Function()

原来Object是由系统自Function 创建的.怎么证明呢?

alert(Object);//Object()
delete Object;//true
Object;//ReferenceError: Object is not defined

但是你不能delete Function.

Function就是一切

(反思到这里了)

因此我们讨论javascript对象的时候不要用class-based OO 的概念去靠(经csf178指正),找原型 constructor 是关键

当然javascript提供了更直观的prototype 属性来实现OO方法的问题.

new 这个运算符具有一定的魔术性

function fun1(){this.n=3;}
function fun2(){this.n=3;return {};}
var foo1=new fun1;//{n:3}
var foo2=new fun2;//{}

 也就是说原型 constructor 的return值是对new有影响的.这就是new的魔术性

分享到:
评论
18 楼 csf177 2008-06-26  
ECMA对这个倒是没明确规定
但是按照ECMA262的意思 Object Function Array等并非GlobalObject的特权属性 所以应该都可以正确删除
所以虽然标准没有明确的规定 也不应该认为是implementation dependent的

FireFox在此处显然属于实现错误
因为alert(delete Function);是true

说实话 如果你读了SpiderMonkey源码 你会对它有很深的绝望
17 楼 achun 2008-06-26  
<p>还真的是实现有很大却别呀,<br/>Moz和IE的实现当中</p>
<pre name='code' class='js'>delete Object;
alert(typeof Object);
delete Function;
alert(typeof Function);</pre>
<p> 还真不一样.这个世界可真乱呀!</p>
<p> </p>
16 楼 csf177 2008-06-25  
<div class='quote_title'>achun 写道</div>
<div class='quote_div'>
<div class='quote_title'>soni 写道</div>
<div class='quote_div'>什么叫顶级的?是不是就是语言内建的叫顶级的?</div>
<p><br/>我也是这么理解的.不过还是用官方的说法比较合适.<br/><a href='http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Predefined_Core_Objects' target='_blank'>Predefined Core Objects</a></p>
<p>预定义核心对象,</p>
<p>问题是内建这个词没有一个定义,Object是系统一运行就建立的,算不算内建呢?</p>
<p>但是Objcet肯定不算Core Objects,因为官方列表中就没有.</p>
<p> </p>
</div>
<p>好像没什么区别吧 这些都可以delete</p>
<p>Moz写的文档只是把Object单拿出来说了</p>
<p> </p>
<p>不管怎么说ECMA现在比Moz更官方 ECMA现在是把它们放一起的</p>
15 楼 achun 2008-06-25  
<div class='quote_title'>soni 写道</div>
<div class='quote_div'>什么叫顶级的?是不是就是语言内建的叫顶级的?</div>
<p><br/>我也是这么理解的.不过还是用官方的说法比较合适.<br/><a href='http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Predefined_Core_Objects' target='_blank'>Predefined Core Objects</a></p>
<p>预定义核心对象,</p>
<p>问题是内建这个词没有一个定义,Object是系统一运行就建立的,算不算内建呢?</p>
<p>但是Objcet肯定不算Core Objects,因为官方列表中就没有.</p>
<p> </p>
14 楼 soni 2008-06-25  
什么叫顶级的?是不是就是语言内建的叫顶级的?
13 楼 achun 2008-06-25  
<div class='quote_title'>soni 写道</div>
<div class='quote_div'>lz想要说什么?</div>
<p>我想搞清楚几件事情,经过csf178的讨论,已经清楚了.就几句话.</p>
<p> </p>
<p>javascript是基于原型(<strong>prototype-based</strong>
)的语言.</p>
<p>javascript具有面向对象(<span style='color: #000000;'><strong>Object-Oriented</strong>
</span>
)的编程风格.</p>
<p><strong>变量不一定是对象(undefined,null等就是特例,但是NaN是个对象)</strong></p>
<p><strong>对象一定有值,也有成员(函数,属性)</strong></p>
<p><strong>Object不是顶级的,因为可以delete Object</strong></p>
<p><strong>顶级</strong>的有:</p>
<p style='background-color: #ffffff; padding-left: 30px;'> <strong><span style='color: #000000;'>Array Object<br/>Boolean Object<br/>Date Object<br/>Function Object<br/>Math Object<br/>Number Object<br/>RegExp Object<br/>String Object</span></strong></p>
<p><strong>new</strong>运算符具有一定的<strong>魔术性,这个说法我语言上还组织不好.</strong></p>
12 楼 soni 2008-06-25  
lz想要说什么?
11 楼 csf178 2008-06-21  
<div class='quote_title'>achun 写道</div>
<div class='quote_div'>
<div class='quote_title'>csf178 写道</div>
<div class='quote_div'>还有个小细节 其实<br/>alert({}.constructor);在FF里也是可以的<br/>{}.constructor;会有问题也是因为词法冲突 {}不在表达式中的时候会被认作语句块(而不是对象构造)<br/></div>
<p><br/><a href='http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Literals' target='_blank'>Object Literals</a> 中</p>
<div class='quote_title'>写道</div>
<div class='quote_div'>An object literal is a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces ({}). You should not use an object literal <strong>at the beginning of a statement</strong>. This will lead to an error or not behave as you expect, because the { will be interpreted as the beginning of a block.</div>
<p> 明确了这种用法是会产生错误的.这种用法也就成了语法错误了,也就是你说的解析时候造成<strong>词法冲突</strong></p>
<p> </p>
</div>
<p>嗯 是这个意思</p>
<p>另外 其实constructor并不是很准 因为constructor可以被修改</p>
<p>在FF中 __proto__ 属性是原型链</p>
<p>var t={__proto__:{a:1,b:2},c:3}</p>
<p>alert(t.a);//1</p>
<p>alert(t.b);//2</p>
<p>alert(t.c);//3</p>
<p> </p>
<p>在JS中 new和函数的prototype可以看作是提供了一种用原型模拟类的方式 </p>
<p>把拥有同一个原型的一组对象看作属于一个类</p>
<p> </p>
10 楼 achun 2008-06-21  
<div class='quote_title'>csf178 写道</div>
<div class='quote_div'>还有个小细节 其实<br/>alert({}.constructor);在FF里也是可以的<br/>{}.constructor;会有问题也是因为词法冲突 {}不在表达式中的时候会被认作语句块(而不是对象构造)<br/></div>
<p><br/><a href='http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Literals' target='_blank'>Object Literals</a> 中</p>
<div class='quote_title'> 写道</div>
<div class='quote_div'>An object literal is a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces ({}). You should not use an object literal <strong>at the beginning of a statement</strong>. This will lead to an error or not behave as you expect, because the { will be interpreted as the beginning of a block.</div>
<p> 明确了这种用法是会产生错误的.这种用法也就成了语法错误了,也就是你说的解析时候造成<strong>词法冲突</strong></p>
<p> </p>
9 楼 csf178 2008-06-21  
还有个小细节 其实
alert({}.constructor);在FF里也是可以的
{}.constructor;会有问题也是因为词法冲突 {}不在表达式中的时候会被认作语句块(而不是对象构造)

JS词法其实挺烦人的 {}这些还好 正则表达式的 / /语法跟除号的冲突 导致JS成为少数产生式不能完全描述词法的语言


顺便 我补充一点 关于new 可以从SpiderMonkey源码看看比普通的函数调用究竟多了什么
js_InvokeConstructor是new调用函数
js_Invoke就是普通的调用

下面代码第56到第59行是调用js_Invoke 其他部分就是new比普通函数多出来的部分
注释很清楚

JSBool
js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc)
{
    JSFunction *fun;
    JSObject *obj, *obj2, *proto, *parent;
    jsval lval, rval;
    JSClass *clasp, *funclasp;

    fun = NULL;
    obj2 = NULL;
    lval = *vp;
    if (!JSVAL_IS_OBJECT(lval) ||
        (obj2 = JSVAL_TO_OBJECT(lval)) == NULL ||
        /* XXX clean up to avoid special cases above ObjectOps layer */
        OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass ||
        !obj2->map->ops->construct)
    {
        fun = js_ValueToFunction(cx, vp, JSV2F_CONSTRUCT);
        if (!fun)
            return JS_FALSE;
    }

    clasp = &js_ObjectClass;
    if (!obj2) {
        proto = parent = NULL;
        fun = NULL;
    } else {
        /*
         * Get the constructor prototype object for this function.
         * Use the nominal 'this' parameter slot, vp[1], as a local
         * root to protect this prototype, in case it has no other
         * strong refs.
         */
        if (!OBJ_GET_PROPERTY(cx, obj2,
                              ATOM_TO_JSID(cx->runtime->atomState
                                           .classPrototypeAtom),
                              &vp[1])) {
            return JS_FALSE;
        }
        rval = vp[1];
        proto = JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL;
        parent = OBJ_GET_PARENT(cx, obj2);

        if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) {
            funclasp = ((JSFunction *)JS_GetPrivate(cx, obj2))->clasp;
            if (funclasp)
                clasp = funclasp;
        }
    }
    obj = js_NewObject(cx, clasp, proto, parent);
    if (!obj)
        return JS_FALSE;

    /* Now we have an object with a constructor method; call it. */
    vp[1] = OBJECT_TO_JSVAL(obj);
    if (!js_Invoke(cx, argc, JSINVOKE_CONSTRUCT)) {
        cx->weakRoots.newborn[GCX_OBJECT] = NULL;
        return JS_FALSE;
    }

    /* Check the return value and if it's primitive, force it to be obj. */
    rval = *vp;
    if (JSVAL_IS_PRIMITIVE(rval)) {
        if (!fun) {
            /* native [[Construct]] returning primitive is error */
            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                 JSMSG_BAD_NEW_RESULT,
                                 js_ValueToPrintableString(cx, rval));
            return JS_FALSE;
        }
        *vp = OBJECT_TO_JSVAL(obj);
    }

    JS_RUNTIME_METER(cx->runtime, constructs);
    return JS_TRUE;
}
8 楼 csf178 2008-06-20  
achun 写道
csf178 写道
achun 写道
果然有纰漏.
谢谢楼上两位.
同时修改了帖子,加入了一些反思的结果
引用
...Aiming的书吧...

偶E问太差,看不了呀!

Aiming的书是中文的啊

Aiming==周爱民


嘻嘻,都说了E文不好了.
Aiming也是E文表示的吧!
javascript的实体书只看过一本,Ajax and REST Recipes
还感觉对自己没有什么帮助(因为偶有自己完整的解决方案),所以就不再买了.
失误呀!


为啥我刚说到这本书就有看似枪文的东西出现......
http://www.iteye.com/topic/206407
7 楼 achun 2008-06-20  
csf178 写道
achun 写道
果然有纰漏.
谢谢楼上两位.
同时修改了帖子,加入了一些反思的结果
引用
...Aiming的书吧...

偶E问太差,看不了呀!

Aiming的书是中文的啊

Aiming==周爱民


嘻嘻,都说了E文不好了.
Aiming也是E文表示的吧!
javascript的实体书只看过一本,Ajax and REST Recipes
还感觉对自己没有什么帮助(因为偶有自己完整的解决方案),所以就不再买了.
失误呀!
6 楼 csf178 2008-06-20  
achun 写道
果然有纰漏.
谢谢楼上两位.
同时修改了帖子,加入了一些反思的结果
引用
...Aiming的书吧...

偶E问太差,看不了呀!

Aiming的书是中文的啊

Aiming==周爱民
5 楼 achun 2008-06-20  
果然有纰漏.
谢谢楼上两位.
同时修改了帖子,加入了一些反思的结果
引用
...Aiming的书吧...

偶E问太差,看不了呀!
4 楼 KKFC 2008-06-20  
说的好 刚搜索到早期的post:
《关于JavaScript的 貌似类(pseudo-classes)----不吐不快》
http://www.iteye.com/topic/85966
3 楼 csf178 2008-06-20  
去看Aiming的书吧 那本书比较靠谱
目前ECMA没有翻好的中文版
2 楼 csf178 2008-06-20  
prototype-based是OO的一种 wiki上说的很确切
js是OO的 ECMA-internal说的也很确切

9.constructor;//SyntaxError  
这个其实根对不对象没关系 纯粹是因为浮点数跟.运算的词法冲突

有些值类型可以.运算是因为.的时候默认转换成了对应的object

引用
我们讨论javascript对象的时候不要用OO的概念去靠


我觉得楼主思想很好 不过有些概念还是要注意一下 这样说比较合适:
引用
我们讨论javascript对象的时候不要用class-based OO的概念去靠

1 楼 KKFC 2008-06-20  
说得很精准确切,————收了

相关推荐

    JavaScript中的原型和继承详解(图文)_.docx

    例如,JavaScript 中的数组是一个对象,包含多个值,并具有push、reverse 和 pop 等方法。我们可以使用这些方法来操作数组对象。 二、原型 在 JavaScript 中,每个对象都有一个隐蔽的状态,即对另一个对象的引用,...

    JavaScript:对象与原型链教程

    ### JavaScript:对象与原型链教程 #### 一、概述 本教程旨在深入解析JavaScript中对象的概念及其核心机制——原型链。我们将从数据类型入手,逐步探索函数与作用域的细节,并重点讨论对象与属性的相关知识。 ###...

    Javascript原型对象、this的5钟用法、原型继承、Caller和Callee的使用.docx

    JavaScript中的原型对象、this的五种用法、原型继承以及Caller和Callee的使用是JavaScript编程中的核心概念。首先,让我们深入理解每个概念。 **原型对象(Prototype)** 在JavaScript中,每当定义一个函数,都会...

    再践javascript对象、原型、属性、构造函数、扩展、json.docx

    ### JavaScript对象、原型、属性、构造函数、扩展、JSON #### JavaScript对象类型 JavaScript是一种广泛使用的脚本语言,尤其在Web开发中占据了重要的地位。它支持多种对象类型,包括内部对象、基于类的对象以及...

    JavaScript面向对象编程指南

    JavaScript通过原型链实现继承,即一个对象可以访问其原型对象的属性和方法。通过`__proto__`或`Object.getPrototypeOf`访问原型。 4. **原型式继承** 在没有类的情况下,JavaScript使用原型式继承模拟面向对象...

    Javascript面向对象基础.rar

    当试图访问一个对象的属性时,JavaScript会查找该对象自身,然后沿着原型链向上查找,直到找到该属性或到达原型链的顶端。 4. **原型对象的修改** 可以通过`__proto__`属性或`Object.getPrototypeOf`方法获取一个...

    深入理解javascript原型和闭包.pdf

    JavaScript原型和闭包是这门语言中两个比较难以理解且与其他面向对象语言区别较大的概念。理解这两个概念,不仅能让我们更深层次地理解JavaScript,而且有助于我们了解编程语言的设计思路,拓宽我们的视野。 首先,...

    举例说明JavaScript中的实例对象与原型对象_.docx

    在JavaScript中,实例对象与原型对象是两种关键的概念,它们构成了JavaScript对象继承的基础。每当你创建一个新的对象实例,它都会有一个内部链接到它的构造函数的原型。这个原型对象包含了可以通过实例对象访问的...

    即用即查JavaScript核心对象参考手册附书光盘

    JavaScript的继承机制基于原型,每个对象都有一个prototype属性,指向它的构造函数的原型对象。通过原型链,我们可以访问到对象的属性和方法,即使它们没有直接在当前对象上定义。 5. **作用域和闭包** ...

    学习javascript面向对象 理解javascript原型和原型链

    当读取对象的属性时,JavaScript首先在对象实例本身上查找,如果找到了,则直接返回该属性值。如果没有找到,它会继续沿着原型链向上查找,直到找到相应的属性或者到达原型链的末端。因此,对象的属性查找实际上是一...

    即查即用-JavaScript核心对象参考手册.rar

    总的来说,这份“即查即用-JavaScript核心对象参考手册”涵盖了JavaScript的基础到高级知识,包括核心对象、数据类型、控制流、函数、原型继承、事件处理、DOM操作以及异步编程。对初学者来说,这是一份非常全面且...

    深入浅出JavaScript对象模型

    当尝试访问一个对象的属性时,如果该对象本身没有定义该属性,则JavaScript引擎会沿着该对象的原型链向上查找,直至找到该属性为止。 每个JavaScript对象都有一个内部属性`[[Prototype]]`,指向另一个对象。当创建...

    JavaScript对象原型链原理详解

    在了解JavaScript对象原型链原理之前,我们需要先理解JavaScript中的对象、原型以及原型链的基本概念。 JavaScript中的对象是一种复合值,它将许多值(原始值或其他对象)聚合在一起,可以通过名称访问这些值。对象...

    javascript面向对象教程

    5. **组合和模拟类**:由于JavaScript没有内置的类概念,开发者通常使用构造函数和原型模拟类的行为,通过`call`和`apply`方法实现方法的共享,通过`Object.create`创建基于特定原型的新对象。 6. **模块和封装**:...

    javascript 面向对象技术基础教程第1/2页

    JavaScript中的原型链机制允许对象继承原型对象的属性和方法,实现一种基于原型的继承。 JavaScript还提供了特殊的方法来枚举对象的属性,如for...in循环,它允许遍历对象中所有的可枚举属性,包括那些通过原型链...

    javascript面向对象要点总结

    本文将深入探讨JavaScript面向对象的关键概念,包括构造函数、原型链、继承以及作用域等。 #### 构造函数与实例化 构造函数是用于创建特定类型对象的函数。通过使用`new`关键字,我们可以基于构造函数创建对象实例...

    javaScript面向对象的编程

    而在JavaScript中,对象更像是一个包含键/值对的字典,通过`.`或`[]`运算符来访问或修改对象的属性和方法。例如: ```javascript // 创建一个空对象 var obj = new Object(); // 设置一个日期属性 obj.Now = new ...

    javascript面向对象编程

    1. **基于对象**:JavaScript中的所有数据都是对象,无论是基本类型如数字、字符串、布尔值,还是更复杂的自定义对象。这种基于对象的特性使得JavaScript具备了丰富的数据处理能力。 2. **封装**:通过函数和作用域...

Global site tag (gtag.js) - Google Analytics