javascript中对象与原型的理解;null和undefined的理解

对象与原型

【ES5 4.3.3 对象类型的成员。对象是属性的集合,并有一个原型对象。原型可以是空值。

【ES5 4.3.5】原型 (prototype)

 为其他对象提供共享属性的对象。

当构造器创建一个对象,为了解决对象的属性引用,该对象会隐式引用构造器的“prototype”属性。通过程序表达式 constructor.prototype 可以引用到构造器的“prototype”属性,并且添加到对象原型里的属性,会通过继承与所有共享此原型的对象共享。另外,可使用 Object.create 内置函数,通过明确指定原型来创建一个新对象。

ss.__proto__.constructor.prototype==Person.prototype

 

 javascript中对象与原型的理解;null和undefined的理解

1 构造函数

 javascript中对象与原型的理解;null和undefined的理解javascript中对象与原型的理解;null和undefined的理解

2 构造函数的原型                               图3实例对象

 javascript中对象与原型的理解;null和undefined的理解javascript中对象与原型的理解;null和undefined的理解

 

1、每一个实例的内部包含一个指针[[prototype]](内部属性),指向对应的构造函数的prototype属性。[[prototype]]属性在脚本中没有标准的访问方式,但在FFChromeSafari中(IE11也有)在每个对象上都支持一个属性__proto__

(如图2和图3中的Person.prototype==ss.__proto__//true

【ES5 4.2.1】每个由构造器创建的对象,都有一个隐式引用( 叫做对象的原型 ) 链接到构造器的“prototype”属性值

【ES5 8.6.2】所有对象都有一个叫做 [[Prototype]] 的内部属性。此对象的值是 null 或一个对象,并且它用于实现继承。

 

2、_ _proto_ _属性是属于对象的,js中除了基本类型都是对象。

【ES5 4.2.1】再者,原型可能有一个非空 (non-null) 隐式引用链接到它自己的原型,以此类推,这叫做原型链 。

原型链的连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间

如图2所示Person.prototype原型也有__proto__属性

图3的原型链:

ss.__proto__.__proto__==Object.prototype //true

ss.__proto__.constructor==Person  //true

ss.__proto__.__proto__.constructor==Object //true

3prototype属性是属于构造函数的?

【ES5 4.2.1】每个构造器是一个拥有名为“prototype”的属性的函数。此属性用于实现基于原型的继承和共享属性。

 prototype属性指向函数的原型对象,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性指向prototype属性所在的函数指针。

Person.prototype.constructor==Person //true

4isPrototypeOf()方法从本质上讲,如果对象的[[prototype]]指向调用IsPrototypeOf方法的对象(Person.prototype),那么这个方法就返回true

ES5中新加的Object.getPrototypeOf()方法直接返回[[prototype]]的值。

function Person(name){

this.name=name;

}

 

Person.prototype.hao=3;

var cc=new Person('cunny');

Person.prototype={

   //constructor:Person,

   age:11,

sex:'nan'

};

var ss=new Person('suuny');

console.log( ss instanceof Person) //true

console.log( cc instanceof Person) //false

 

console.log(ss.__proto__==Person.prototype) //true

console.log(cc.__proto__==Person.prototype) //false

 

console.log(Person.prototype.isPrototypeOf(ss)) //true

console.log(Person.prototype.isPrototypeOf(cc)) //false

 

console.log(ss.__proto__.constructor.prototype==Person.prototype) //false

console.log(ss.__proto__.constructor.prototype==Person.prototype)//false

 javascript中对象与原型的理解;null和undefined的理解javascript中对象与原型的理解;null和undefined的理解

     cc的原型对象                    ss的原型对象

重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系;它们引用的仍然是最初的原型

 

Nullundefined

【ES5 4.3.9】未定义值 (undefined value)

 说明一个变量没有被分配值的一个原始值。

【ES5 4.3.10】未定义类型 (Undefined type)

 拥有唯一值“未定义值”的类型。

【ES5 4.3.11】空值 (null value)

 代表对象值故意留空的一个原始值。

【ES5 4.3.12】空类型 (Null type)

 拥有唯一值“空值”的类型。

1null 表示一个值被定义了,定义为“空值”;

2undefined表示根本不存在定义。toNumber时,null转换为0undefined转换为NAN

3、在ES6中使用参数默认值时,若参数被省略或值为undefined,则取该参数的默认值,如果传入null,则函数中的对应参数就被赋值为null

所以设置一个值为 null 是合理的,如

objA.valueA = null;

但设置一个值为 undefined 是不合理的,如

objA.valueA = undefined; // 应该直接使用 delete objA.valueA;任何一个存在引用的变量值为undefined都是一件错误的事情。

这样判断一个值是否存在,就可以用

objA.valueA === undefined // 不应使用 null因为undefined == null,而null表示该值定义为空值。

这个语义在JSON规范中被强化,这个标准中不存在undefined这个类型,但存在表示空值的null。在一些使用广泛的库(比如jQuery)中的深度拷贝函数会忽略undefined而不会忽略null,也是针对这个语义的理解。

4JS 中同时存在 undefinednull是合理的。

首先在 Java 中不存在undefined是很合理的:Java是一个静态类型语言,对于Java来说不可能存在一个“不存在”的成员(不存在的话直接就编译失败了),所以只用null来表示语义上的空值。而JavaScript是一门动态类型语言,成员除了表示存在的空值外,还有可能根本就不存在(因为存不存在只在运行期才知道),所以这就要一个值来表示对某成员的getter是取不到值的。

至于 dart 不存在 undefined,最大原因恐怕是dartjava一样是一个静态类型语言(或者说是一个有编译期静态类型检查的语言,在运行期并不进行类型检查),所以可以不需要设立一个undefined这样的类型。

虽然这两个东西的区别确实会令初学者困扰,但掌握并理解这两个值的语义实际上和理解 prototype/scope一样是非常重要的。

3. typeof null 结果是 ”object“ 更像是一个设计失误

因为 typeof null === "object" 而认为 null 语义是表示空对象是个不谨慎的猜测,感觉像是先射箭后画靶一般。简单的反例:在强类型数据交换协议odatahttp://www.odata.org/)的JSON格式中,即使一个成员定义为特定类型(比如string),也可以设置其值为null来表示这个值是空值,这可不是表示这个成员是空对象,只是说值为空而已(和空字符串、0false有所区别)。

typeof null === "object" 更可能是一个设计失误,所以在 harmony 中有提议将这个返回值修正为null :

http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null

当然该提议因为会造成大量旧 Javascript 脚本出现问题而被否决了……

4、若你尝试对某元素引用一个该元素并不支持的事件,你会发现该元素的'on事件名'属性是undefined。但如果某事件被该元素所支持,但事件处理函数没设置,那么'on事件名'null

<button id='btn'>haha</button>

var btn=document.getElementById('btn');

console.log(btn.onclick)//null,button没有设置click事件处理程序
console.log(btn.ondone) //undefined,button不支持done事件

"null是一个表示""的对象,转为数值时为0undefined是一个表示""的原始值,转为数值时为NaN"

null表示一个空对象指针,可以使用null保存对象的变量但还没有真正保存对象