转载: js的值,对象,原型
本文转载自: http://www.iteye.com/topic/206218
基于类型的语言 | 基于原型的语言 |
1.类型和实例是不相同 | 所有的对象都是实例 |
2.以类型定义定义类;以构造函数实例化 | 定义和创建一组带有构造函数的对象 |
3.用new运算符创建一个简单对象 | 相同 |
4.通过使用类型定义去定义存在类型的子类来构建对象的层次 | 以赋值一个对象带有构造函数作为的原型来构建对象层次 |
5.通过类型链继承属性 | 通过原型链继承属性 |
6.类型定义指定了一个类型的所有实例的所有属性.不能在运行时动态增加属性 | 构造函数或者原型指定了一组初始的属性.可以对一个对象或者一组对象动态的增加和删除属性。 |
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的魔术性