JS的易混淆概念辨析

在JS中将“(O/o)bject”这个单词翻译成对象绝对是最蛋疼的翻译。很多时候我们我们表述不清就是因为这个词。先理一下:

1.我们说“对象实例”这个比较明确,就是仅指“一个实例”。而我们说“对象”根据语境有时候是说“对象类型”,有时候是说“对象实例”。

2.“对象类型”这个表述范围>="Object类型"。JS除基本类型外,还有引用类型。而引用类型又分为(预置)构造类型包装类型。其中(预置)构造类型有:Object类型,Array类型,Date类型,RegExp类型和Function类型。包装类型有:Boolean类型,Number类型和String类型。(预置)构造类型和包装类型可统称为对象类型(这是我们表面上说的JS里一切皆对象)。此处的“对象类型”显然大于"Object类型"。为方便交流,我们说对象类型就指这个统称,而Object类型就是纯粹的Object类型(不用翻译),不再因Object单词的翻译为对象而说其为对象类型。这样对象类型总是大于Object类型。插一句话,构造类型除了JS已经提供的预置构造类型外,我们可以自定义构造类型,也就是自定义一个function然后用这个function去new对象(实例)。

3.首字母大写和小写有区别: Object偏重指对象类型,object偏重指对象实例; Function和function等同理。我们常说的object对象,其实是指预置或自定义的Object(类型的)对象实例。

4.第2条中的分法是从应用角度分的,如果从生成角度来说,JS是没有XX类型的,因为从生成角度来说JS里只有一个个的对象实例(这是我们真正理解的JS里一切皆对象)。所有的对象(实例)总分为两类:普通对象(不是由 new Function() 创建的对象,用typeof去检测时返回“object”)和函数对象(由 new Function() 创建的对象,用typeof去检测时返回“function”)。

5.第2条中的XX类型本意是指由构造器函数Object(), Array(), Function()……等new出的对象(实例)的总称。而这些预置构造器函数包括包装类型的构造器自定义构造器也是一个对象实例,它们都是new Function()出来的实例。值得注意的是Function()构造器也是new Function()出来的实例,自己生出自己,自己当自己的妈!除了它,别人都是Function()这个妈的孩子。就因为如此,所以Function比较特殊,别人的X.prototype原型对象用typeof求是“object”,而它Function.prototype用typeof求是“function”,我们知道JS中所有函数对象(普通对象没有)都有prototype属性,既然Function.prototype是一个function对象那就仍有原型对象可求,我们在此基础上再求一次prototype得:typeof Function.prototype.prototype的值为undefined,走到了尽头。所以,从应用角度来说Function()构造器和其他构造器没啥两样都是平级,但从生成角度来说Function()构造器是其他构造器之母,高一个等级。

6.由第5条可知,JS总是通过一个老对象实例来创建新对象实例,由于是对象创对象故称其为基于对象的编程(OBP),而其他语言比如C++是通过类来实例化对象,故称为面向对象编程(OOP)。由于JS没有类的概念,所以要用构造器函数模拟类用原型和原型链来模拟实现继承。

7.(先记在这里以后专门写原型和原型链)x.prototype是x对象的一个属性,这个属性可以理解为是一个引用或指针(当然JS里没有指针这一概念),它指向一个匿名对象,该匿名对象在我们交流时给它起个名字叫——X Prototype对象,这就是原型对象。(有人说是“对象原型”,这种表述不正规。)我们有时候会直接用x.prototype指代X Prototype这个原型对象(取了名字的匿名对象-_-b),这是方便但不严谨的表述方法,需要知道。

8.说一下constructor。在JS中只有函数对象和原型对象真正具有constructor,其他对象不真正具有。但由于这些对象的_proto_属性指向了原型对象,故其就继承了consturctor,所以我们可以认为这些对象有constructor。理解了这句话也就知道了继承就是看_proto_属性的指向,改变指向就改变了继承。进而可知修改原型对象重写(重赋值)原型对象在继承表现上的区别,及对constructor指向上的影响。

9.最后说一下null。它是JS语言中遗留的bug。null 本应该作为一个独立的数据类型和值即null纯粹就是null,但JS中typeof(null)的值是"object"。我们知道JS中所有对象(无论普通对象还是函数对象)都有_proto_属性,那你既然是object,我就看看你里面的_proto_属性指向哪里,不过对不起,JS规定null里没有_proto_属性。有两种方案可以解决这个bug,要么是给null一个_proto_属性让他指回null;要么是还原null的纯粹性而不作为一个object存在。但由于历史遗留代码太多, JS新订标准拒绝修改此bug,故遗留至今。

猜你喜欢

转载自blog.csdn.net/lianfengzhidie/article/details/81151910