JS对象-继承-私有成员

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)

<完>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值