JS“对象”破冰之旅(一)

326 阅读6分钟

原文链接

“没有对象?new一个~”。前端圈儿的人应该都知道这句话。这个“对象”即是我们要讨论的对象。

《高程》的前言是这样形容JS的——JavaScript是一种非常松散的面向对象语言。这句话的分量之重,即使你可能还不明白,也应该能预见到,JS中很多东西都生长在“对象”这个土壤之上,至于长什么样,咱往下看。

对象

面向对象编程,又称OOP,拥有此特性的语言,通常都有“类”的概念,通过类,可以创建任意多个具有相同属性和方法的对象。

但偏偏...ES中没有“类”的概念,不过它有一个跟“类”相似的东东,叫做引用类型

每个对象,都是基于一个“引用类型”创建的,我们常说,先创建一个对象,再创建一个此对象的实例,那么,其实“对象”就是某个引用类型的实例,那引用类型是什么?

引用类型

简单地说,JS中的数据类型分为两种:一是基本类型,二就是引用类型

基本类型有:Number,String,Boolean,Null,Undefined

引用类型则有:Object,Array,Date,RegExp,Function

基本类型很好理解,就像我们将课程分为语文、数学一样,但引用类型怎么理解?

其实引用类型就是一种将功能数据组织在一起的数据结构,即,有什么能干什么

说半天,我们来创建一个Object的实例:

var person = new Object();

就像HTML中写标签我们随手就可以写个div,新建对象我们可以像这样使用Object,它是ES中使用最多的一个类型,虽然它不具备多少功能,但是用来存储和传输数据也是不错。

当然,空的对象似乎没什么用处,我们可以给对象赋予一些属性或者方法,就像这样:

person.firstname = "Bill";
person.lastname = "Gates";
person.age = 56;
person.run = function(){
    return "I can run!";
}

这里为对象person添加了属性“name、age”和方法“run”。也就是前面说的“有什么”和“能干什么”,这是一种很常规的创建对象实例的方式。

还有另外一种也很常见,就是对象字面量,比如刚才的person实例可以写成这样:

var person = {
    firstname:"bill",
    lastname:"Gates",
    age:56,
    run:function(){
        return "I can run!"
    }
}

(有个细节,这里的属性之间是用逗号分隔的,但最后一个属性后面没有加,这是因为IE7及更早的浏览器和Opera中会报错,但这个错误,现在已经不重要了,低版本浏览器几乎已经全部退出历史舞台)

这种写法给人的感觉就是,简洁明了,更像是以个封装数据的独立单元,因此得到很多开发者的喜爱。

那么,可以想见,既然可以这样创建Object,其他几种是否也可以?答案是肯定的。比如:

//一个长度为100的数组
var classmate = new Array(100); 
// 一个日期对象
var now = new Date();  
//一个加法函数对象
var sum = function(sum1,sum2){  
    return sum1+sum2;
}

这几种,属于JS的内置对象,也就是说,无需定义,它本身就具备,而且有很多的原生属性和方法供使用。

到这,你可能有疑问了,既然说JS中所有东西都是对象,那么,基本类型呢,它们可是跟引用类型划清了界限的,怎么跟对象扯上关系呢?

基本包装类型

其实,为了便于开发者操作基本类型的数据,ES提供了一种叫做“基本包装类型”的东西,即“Number、String、Boolean”,它同时具备引用类型和基本类型的部分特征,比如我们可以像这样定义一个字符串:

var s1 = "some text";

就相当于这样:

var s1 = new String("some text");

(但为了和引用类型相区分,一般不提倡显式定义,除非有必要)

基本类型本身应该是没有方法的,这样以来,它就像特技加身一样有了很多方法来操作,像字符串的concat()、slice()、substr()等,我们后续聊字符串再详述,”Number”和“Boolean“同理。所以,应该能够理解,为什么说它们也在对象的管辖范围内。

但基本包装类型和引用类型还是有区别的,主要是对象的生存期

使用new操作符创建的引用类型实例,在执行流离开当前作用域之前都是一直在内存中的,而自动创建的基本包装类型对象,只存在于一行代码执行的时候,然后立即被销毁,这意味着,我们不能在运行时为基本类型添加属性和方法。

好,到这里差不多结束了,可是...我们好像漏了几个很重要的东东,前方有雾,小心走路~

单体内置对象

在前面的文章中我们说过,JS中,有些东西,你根本没看到哪里有定义或者创建,它就已经存在了,比如单体内置对象,它不依赖于宿主环境,不需要开发者显式创建,就已经实例化。

两个单体内置对象:Global和Math。

Global

开发过程中,我们常见的一种保障性做法叫“兜底”,那么Global对象就是负责为JS兜底的,有任何不属于其他对象的属性或方法,最终都会是它的属性或方法,比如常见的parseInt()、parseFloat()等。

ES中没有给出直接访问Global对象的方法,但浏览器将它作为window对象的一部分加以实现,因此,在全局作用域中声明的所有变量和函数,就都成为window对象的属性,比如:

var name = “tom”;
 function sayName(){
     alert(window.name);
 }
 window.sayName(); //"tom"

window对象除了扮演Global对象的角色,它还有很多别的任务,后续单聊。

Math

可以这么说,不论哪个领域的问题,最终都能归结为数学的问题,甚至有这样的名言:数学方法渗透并支配着一切自然科学的理论分支。它愈来愈成为衡量科学成就的主要标志。 —— 冯纽曼

所以,作为一个极为重要的工具,JS当中当然不能缺少数学方法。

随便举几个例子:取整、随机数、最大/最小值、绝对值。

怎么样,是不是非常有用,同样,这里只简要引见,不再赘述。

总结

本文试图简明扼要、通俗易懂地介绍对象,从何而来,有什么特点,有哪些分类,有什么用途,不知是否达到本意,只是对象的知识点实在太过繁多,且有些地方极抽象,即使概括来说,一篇文也是不够的,有待后续接着聊,回见!~