Javascript基础回顾之(一) 类型
本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对javascript的一些基本原理普遍存在这里或者那里的一知半解,所以决定先花一些时间整理一下这些基础知识和大家分享。 刚开始是打算写一篇的,但是后来写着写着就发现越来越多,所以决定还是写一个系列吧。本系列所有内容都是涉及javascript基础的,没有时髦的玩意儿,但是我相信这些基础的东西会有助于你理解那些有趣的东西的。
是的,说到javascript我能想到的就是有趣,好玩!那么到底哪些地方好玩,为什么好玩呢?我们一起来玩玩吧,让我们玩着玩着就把javascript理解透彻了。本文所包括的内容:
基本类型
object 与 object
基本包装类型
值类型和引用类型
function类型
基本类型
javascript有5种基本数据类型(也叫简单数据类型):undefined、null、boolean、number、string 和1种复杂数据类型object。
var undefinedvariable; var nullvalue = null; var cnblogs = new object(); var func = function () { }; typeof ("string"); typeof (100); typeof (true); typeof (undefinedvariable); typeof (cnblogs); typeof (undeclaredvalue); typeof (nullvalue); typeof (null) typeof (func)
告诉我结果是什么?
好玩之一: 声明但未赋值 和 未声明的变量都是 undefined
好玩之二: 只有声明并赋值为null,它的值才会null
好玩之三: typeof(object) 竟然是一个function
好玩之四: typeof(null) 竟然是一个object
null 和undefined这两种类型都只有一个值,即null和undefined。从逻辑上看null值表示一个空对象的指针,这就是为什么typeof(null)会返回object。 并且undefined是派生自null值的,所以......
好玩之五: null == undefined 是成立的。
但是想一想,null和undefined毕竟是两种不同的类型,即使他们是父类和子类的关系,在c#里面父类和子类也不能相等啊,不是么?其实null == undefined就是硬性规定,ecma规定它们做相等性测试的时候要返回true所以他们返回true了。就好像我们在c#里面重写了equlas 方法一样。
至于为什么 typeof(object) 返回 function,请看下面的object与object。
object 与 object
javascript高级程序一书中说到 ”函数在ecmascript中是对象,不是一种数据类型”。 好像是译者加上去的,既然typeof(object) 都返回 function了,为什么还说function不是一种数据类型呢?object 和 function之间是什么关系呢?
在我看来,object其实就是一个function,或者我们说object是一个函数的名字比较容易理解,官方名称是构造函数。
var p = new object(); p.name = "jesse"; p.age = 18; function person(name,age) { this.name = name; this.age = age; } var p2 = new person("jesse", 18);
在上面的代码中, 如果我们把object当作一个函数名那么 new object() 和 new person() 性质就是一样的了。通过 new 操作符得到一个 function 实例, 这里面的function就已经是类的概念了。所以这里的object其实是一个function。这样我们就可以解释为什么typeof(object)是function了。
那我们在上面所说的复杂类型object,它又是什么呢?
object是function,但是 new object() 则是 object。到这里面就搞清楚了首字母大写的这个object是一个function,而首字母小写的这个object它才是一种数据类型。所以我建议大家以后说到类型的时候全部用小写,我们的基本类型是 string, number, boolean。大写的string, number, boolean 它们只是一个函数而已。而调用这些函数所得到的结果是,没错,是object。
最后,我们是找不到undefined 和null 这两个函数的,所以这两种数据类型就是undefined和null(为什么typeof(null)会得到object已经说了)
好玩之六: object 不是object类型
基本包装类型
我们上面讲了string, number, boolean是基本类型,基本类型和复杂类型最大的区别就是基本类型没有prototype属性。也就意味着你不能给基本类型随意的添加方法或属性。
var str = "str"; // typeof(str): string var strobj = new string("str"); // typeof(strobj):object strobj.name = "strobj"; strobj.alert = function () { alert(this.name); }; strobj.alert(); // strobj str.name = "str"; //wrong... str.alert = function () { alert(this); } str.alert(); // this is wrong.... nothing is gonna happen.
同时我们还说到了首字母大写的这个string是一个function,所以new string("str")得到的是一个object而不是一个string,这里大家要搞清楚了。我们的问题来了,为什么基本类型string会有一些初始的方法呢?它不是基本类型么?方法是怎么加上去的?
str = str.concat("str2"); strobj = strobj.concat("str2"); strobj.alert(); //之后返回 string 不再是一个对象了, 所以这里也不再有alert方法了。
str是string类型的变量,记住它不是一个对象。它是不应该有方法的,那么它的contact方法从何而来呢?这里后台在调用str.contact的时候实际上偷偷的完成了几步操作:
- 基于str创建一个string类型的实例
- 在实例上调用指定的方法
- 销毁这个实例
将这三个步骤想象成这样:
var str2 = new string(str); str = str2.concat("str2"); str2= null;
我们可以把string,number,boolean叫做封装类型, 他们就好像我们在c#里面的自定义类型一样。 但是不要忘记了我们真正的基本类型是string, number, boolean。用string所构造出来的对象是属于object类型的。
好玩之七: string 不是 string
值类型和引用类型
我们上面讲到了5种基本类型:string, number, boolean, null, undefined 全部是值类型。javascript中只有一种引用类型,也就是我们的复杂类型object。那么有人可能会好奇,那么像date, regex, arrary这些是什么类型呢 ? 其实这里面的概念有一点混淆,如果你很好的理解了上面的object 和object之间的区别,可能会比较好理解一点。 我们可以把function 看成是c#里面 class关键字,我们可以用class定义类,同样我们可以在javascript中用function来定义类。
在c#中定义类:
namespace consoleapplication1 { class person { public string name { get; set; } public int age { get; set; } } class program { static void main(string[] args) { var p =new person(); console.writeline(p.gettype()); // consoleapplication1.person console.readline(); } } }
在javascript定义类:
function person(name,age) { this.name = name; this.age = age; } var p = new person(); typeof(p); //object
你发现区别了么?如果我们在javascript中用function定义类,他们的实例将永远是object, 包括原生的那些date, array, regexp。
typeof (new date()); // object typeof (new array()); // object typeof (new regexp()); // object
好玩之八: 全部都是object
如果全部都是object的话,那我怎么能知道这个对象到底是不是date或者person的实例呢?借助于instanceof 就可以了。
终级好玩:我用function创建了一个person类,然后用new得到一个person的实例,结果它却不是person类型的。 这就好像生了个孩子,供他吃穿,但是他却不跟你姓,这得有多么无私伟大才干得出来的事啊!
function类型
function类型有两种,函数声明和函数表达式。函数声明具有优先级,可以在声明之前被使用,表达式却不能。
saygoodnight(); // right sayhello(); // wrong var sayhello = function (name) { alert("hello, " + name); }; function saygoodnight(name) { alert("good night, "+ name); }
除此之外,函数表达式还可以像object一样,随意的添加属性。
var sayhello = function (name) { alert("hello, " + name); }; sayhello.age = 18; sayhello.sayage = function () { alert("i am" + 18) ; } sayhello.sayage(); // i am 18
但是,函数表达式到底是个什么玩意儿呢? 不能实例化,但是可以随意的添加属性,它和object有什么区别?我们在上面说过,object其实就是一个对象实例。
我们还有大写的function, 它和function之间的关系会不会和string 和string 一样?( 以下内容比较费脑力,慎入!)
var sayhello = new function('name','alert("my name is " + name );'); sayhello('jesse'); sayhello instanceof function; // true var sayhello2 = function (name) { alert('my name is' + name); }; sayhello2 instanceof function; // true
我们上面调用function去构造了一个函数。既没有用函数声明,也没有用函数表达式,不管怎么说这是第三种创建函数的方法,虽然肯定没有多少人用它,因为它不管是参数,还是函数体全部都是字符串,这写起来还不让人崩溃么?
看出什么猫腻来了么?所谓的函数表达式,其实是用一个变量接收了一个function的对象而已。而这个function的对象则是function的实例。包括用函数声明写出来的函数也是function的实例。
function sayhello3(name) { alert('my name is' + name); } sayhello3 instanceof function; // true
但是,等等,我们前面说到的string, date, array都是function类型的,那function也是么?
我们前面说所有function的实例都是object类型的,但是对于function 这个奇异的function来说,它的实例仍然是function类型的,并且我们可以用function的实例再创造实例。原来我们所说的用function创造出来的类,它不是类,而是function的实例。
function person(name) { this.name = name; } person instanceof function; // true
我们再结合自执行函数理解一下,也许会好一点:
(function () { alert("something..."); }());
实际上我们上面的function(){} 会返回给我们一个function的实例,那么我们当然可以直接执行它了。这么看来function应该是javascript里面最特别的类型了。
好玩之十:所有的function都是function的实例
好玩之十一:function 本身也是一个function
最后我们来总结一下:
- javascript中有5种基本类型:string, number, boolean, null, undefined。
- 另外一种复杂类型object 其实是function的实例。
- 除了function这个系统里面的function构造器以外,其它所有function的实例都是object类型的。
- date, array, regexp 这些都是function类型,同时也是function的实例。同理,它们的实例也是object类型的。
总结完了,好像也不多,不是么?关于function其实javascript是非常强大的一个功能,作用域以及面向对象的一些知识也是和它息息相关的,我们下一篇就来看看作用域的问题。谢谢大家的关注!