1

对象

在大多数人的眼里,js是一门面向对象(Object-Oriented)的语言,但是它与其他的语言比如c++,java 这些面向对象语言 略有不同。
!!!艹,说人话
那问几个问题吧:

1.你知道js中对象的定义是什么吗?

答: 不就是一个散列表嘛~ 相当于key/value对.

var obj = {
    name:"jimmy",
    gender:"male"
}

2.那js里面一切都是对象你能理解吗?具体一点,你说一下,函数为什么是对象吧。
答:...。 (Ps:md!!! 函数哪里是对象了。。。)

以上对话其实是一道面试题。 是不是感觉自己蒙蒙哒了~
壮士磨叽, 其实js里面一切都是对象是完全有理有据的。希望能够好好理解,因为这个以后可能会区别你是砖家,还是专家的一个重要分水岭.
来我们先说一说对象.

what's the Object?

这个问题就涉及了对象的定义。 上面说的没错,对象其实就是一个散列表而已。但是更深层次的说,你怎么获得一个对象。
show me u code:

var obj = new Object();

上面一个例子很好的体现出,对象如何定义。
对象其实是由 new + 构造函数 创建的。 关于这点就会涉及到模式的概念,大家有兴趣可以参考我前面一篇文章——"模式之辩". 而且还有一个限制, 你所创建的类型必须是引用类型。
听不懂了吧~
总结下上面的,其实
对象 = new + 构造函数 || 字面量的引用类型
来上个栗子.

var obj = new Function();  //对象
var obj = new Object();  //对象
var obj = {};  //对象
var str = "not a Object";  //不是对象

由于string不是引用类型,所以它创建的实例不是对象~ 而且其他的都是引用类型,所以结果都是对象.
但是对象还有几个features, which are unique with other types.

1.对象的可增添性

什么意思嘞?

var obj = {};
obj.name = "jimmy";
console.log(obj.name); //jimmy
var str = "a";
str.name = "jimmy";
console.log(str.name); //undefined

这个可以充分的说明,对象类型和值类型的区别的。

2.等价判断

怎么判断两个对象是一个东西嘞?
用"==="呗。 来试一试.

var obj1 = new Object();
var obj2 = new Object();
console.log(obj1===obj2);  //false

艹,怎么会这样,两个不都是对象吗?而且我又没动它。应该一样啊~~~
骚年,不要把你判断值类型的方法套在我们伟大的对象上。
说明一下。如果判断对象类型和值类型。
对象类型的判断:
对象的等价是建立在你们的源是否相同(官方的说法叫地址).

var obj1= new Object();
var obj2 = new Object();

需要搞清楚,使用 new + 构造器 你是在新建实例,即你创建的是不同源的对象。
那如何同源嘞?

var obj1 = new Object({
name:"jimmy"
});
var obj2 = obj1;  //同源
var obj3 = new Object();
obj2.name = "sam";
console.log(obj1.name);  //sam
console.log(obj1===obj2);  //true
console.log(obj2===obj3);  //false

其实到这里,我们需要将我们以前的所说的对象再抽象一层。 你说使用的var obj1 里面的obj1 并不是对象,而只是一个指针, 指向着这个对象。 那这个对象在哪里嘞? 在你的内存当中。 艹~~~ 好难理解。
为了大家更好的理解一切都是对象,我这里会以大众的视角来讲解的。(当然如果你已经理解了,可以忽略下面非正式的说法~)
回退~
我们还是将obj1和obj2说成是对象。 上面可以看出,只有是同源的对象才会相等。
值类型的判断:
这个就很好说了, 你知道1===1吗? 恩,知道~~~
恭喜你,你已经知道值类型的判断了。

var num1 = 2;
var num2 = 2;
console.log(num1===num2);  //true

说了这么多,那值类型和引用类型到底有哪些呢?
值类型: string,number,Boolean,null,undefined,Symbol(es6才出的)
引用类型: Object,Array,RegExp,Function,Date
恩,大致就这么多。
~脚嘚玛嘚(Ps:日语)
大哥,不对呀~ 为什么有时候我使用string类型的时候又可以在后面使用方法嘞?您看:

var s = "jimmy";
console.log(s.length);  //5

不是说值类型不是对象吗? 那它怎么会有对象的feature呢?
对,这个问题问的好~
来,再给大家科普一个类型,基本包装类型。

基本包装类型

我相信写过2k+代码的童鞋应该会遇到这样的情况。比如我要知道这个字符串是不是空,可以使用这样的判断:

var s = "jimmy";
if(s.length===0){
    console.log("这是一个空的string");
}

咦~ 为什么值类型的又可以使用属性嘞?
事实上, ECMAScript 规定的类型详细的分有2.5种.
除了上面说的两种还有一种基本包装类型.
基本包装类型: String,Number,Boolean.
其实值类型 包括基本包装类型的。
那他的特性是什么嘞?
再看一下上面的例子:

var str= "jimmy";
console.log(str.length);  //5
str.length = 6;
console.log(str.length);  //5

我们用事实说话, 上面的结果很好的证明了,基本包装类型的特性。 即 如果你想读取值类型的相关属性和方法,
js引擎会默认帮你将值类型,临时变为一个对象使用。但是这层保存存在的时间,只是你代码执行的那一瞬间。
再次证明:

var str = "jimmy";
str.male = "male";  //执行成功,但立即被销毁
console.log(str.male);  //undefined

上面例子的执行过程是

1.给str包装一层对象实例
2.执行对象的一个特性
3.销毁这层包装实例

所以就不难理解,为什么上面会是undefined. (因为没都没了,你哪来的定义嘞)。
综上所述,在js中一切都是对象是不无道理的。
还记得上面说的,对象是由 new + 构造器函数 创建的吗? 所以说 有构造器的类型,都是对象。 事实上除了null,undefined 这两个 呆毛。 其他的类型都有构造器,所以再次声明一切都是对象是很有道理的。
最后我们来回答一下开篇的那个题目,为什么函数也是对象?
如果函数也是对象,那他应该具有对象的一切特性,我这里偷个懒,就举他的动态特性吧。

function a (){};
a.move = 1;
console.log(a.move);  //1

额,不信吗? 我开大了哈~ 用instanceof 检测一下

console.log(a instanceof Object);   // true

完毕~
再补充一点,我整篇都是对象对象的。英文不都是Object. 那为什么Function类型也是Object. RegExp类型也是Object. Object 也是Object. 好了 不绕了, 如果大家如果知道原型链这个东西的话,应该知道,所有的构造器的原型的金字塔尖 就是Object. (null不算啊~ 这个呆毛不算,因为Object再往上就是null了);
下次面试之前理解一下这句话,我相信,你的评级应该会靠SP 更近一点吧。嘿嘿


villainhr
7.8k 声望2.2k 粉丝