JS对象概述
创建Object对象的实例: var o = new Object() ; //没有参数时,可以省略括号
JS中所有的对象都是从Object中派生出来的。
JS中得对象和C++,JAVA的类作用相似,但是本质上不同,JS的对象是通过原型(prototype)来组装的,也就是说,并不是像Java一样,先去定义一个完整的类属性,方法。然后再使用类去创建对象。JS的对象是组装的,随时需要随时通过原型组装进来。
所有的JS定义的变量,函数等都属于window中一个实例。与现实世界类比,window就像是整个宇宙,所有的对象实例都在宇宙之中,对象实例之间可以相互组合形成新的对象,就像宇宙中出现新物种一样。在JS中定义的函数,对象,变量等,都可以在前面加上window.xxx来引用,之前提到的document其实也是宇宙中的一员。
比如 var data = 3;在使用时 data 和 window.data是一模一样的。
由上面论述可推知,JS中的new和Java中得new不是一个概念,java中的new,是按照类规定创建一个新对象,而JS中得new则是用对象中得原型组装一个而已。
所有的数据都是通过内置对象组装起来的Boolean、Number、String、Null、Undefined、Object,Function。
<script>
function func()
{
console.log("函数也是一个对象实例,可以有属性"); //事实上所有函数都是Funciton对象的实例
}
func.data = 3;
func();
console.log(func.data);
</script>
小插曲:Boolean这个对象比较特殊 var oB = Boolean(“false”),因为oB是一个对象,oB在转化为布尔时为true,oB.valueOf为false。
简单对象定义
对象包括两个部分,构造函数和原型。简单的创建模式不需要写构造函数和新创建原型,默认都是从Object的原型继承来得。如果想定义自己的原型和特殊构造过程,则需要用高级对象定义方法
简单对象定义 literal notation(字面声明),在原型Object.prototype的基础上加工自己的数据。
var annimal =
{
canfly:true, //属性
fly:function(/* para可选 */)
{
console.log("fly");
}
};
//声明定义后,还可以添加或删除属性
annimal.walk = function()
{
console.log("walk");
}
//简单对象实例的__proto__都是Object.prototype,也就是说简单对象是从Object组装,继承而来的。
console.log(annimal.__proto__ === Object.prototype) //true
指定对象原型的定义
1)指定原型为匿名对象实例
//需要定义构造函数和原型,prototype原型用于实现继承,共享属性,构造器用来初始化操作。
//构造函数
function Annimal()
{
console.log("constructor"); //初始化操作
}
Annimal.prototype = //这个原型指定为通过简单创建对象的方式创建的一个匿名对象实例
{
canfly:true, //注意成员之间用,号隔开
fly:function(){console.log("Fly");}
}
var annimal = new Animal(); //创建对象时会调用构造函数
console.log(annimal.__proto__) //会输出匿名对象的定义
//annimal实例的原型为上面的匿名对象实例,而匿名对象实例的原型是Object.prototype,所以下面的结果为true
console.log(animal.__proto__.__proto__ === Object.prototype)
2)指定原型为父对象实例,从而实现继承的效果。注意私有成员的实现,继承的实现,子对象在构造函数中添加自己的属性和方法对父原型进行扩展。
<script>
function Animal()
{
console.log("constructor animal"); //初始化操作
}
Animal.prototype =
{
canfly:true,
fly:function(){console.log("Fly");}
}
function Person(age)
{
console.log("constructor person");
//不带this的属性,方法为私有的,不能通过对象实例访问,只能通过内部调用。
var privatevar = 10;
var privatefunc = function (){console.log("I can not fly")}
this.canfly = false //初始化由父类继承而来的属性。
this.fly = privatefunc; //通过内部私有方法赋值实现
this.age = age //在Animal的基础上添加自己的新特性
}
Person.prototype = new Animal();
p = new Person();
p.fly(); //I can not fly
</script>
构造和原型配合的正确写法
每次new对象的时候,构造函数中得内容会被深拷贝,而原型中得内容被浅拷贝,也就是说原型中得引用类型会被所有的实例所共享。所以为了保持统一,且不会出现意料外问题,定义对象类的时候通常的做法是将所有的属性放在构造函数中,方法的定义放在属性中。这样所有的对象实例可以共享方法,减少了很多内存浪费。
//指定对象原型进阶
function Person(){}
Person.prototype =
{
friends:new Array("A", "B"),
friendsnum:2,
}
p1 = new Person()
p2 = new Person()
p1.friends.push("C")
p1.friendsnum = 3
//往其中一个对象中得引用属性中赋值后,另一个也会被修改,标量属性不会被修改。
console.log(p1.friends, p1.friendsnum)
console.log(p2.friends, p2.friendsnum)
等价静态属性
JS中是没有静态方法和属性这个概念的,但是原型中的引用属性和方法是所有的实例共享的,所以某种程度上跟静态是一样的。
function Count()
{
this.number = 1
}
//指定对象原型进阶
function Person()
{
this.instanceNum.number++
}
Person.prototype =
{
instanceNum:new Count()
}
p1 = new Person()
p2 = new Person()
//由于原型中的引用类型是所有的实例共享的,下面两个值相同3,可以实现java中得静态属性。
console.log(p1.instanceNum.number)
console.log(p2.instanceNum.number)
<完>