Day15
●js面向对象特征介绍
1、javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象。
☞特别说明:基于对象也好,面向对象也好实际上都是以对象的概念来编写程序的,从本质上并无区别,所以这两个概念是一样的。
2、因为javascript中没有class(类),所以有人把类也称为原型对象,因为这两个概念从在编程中发挥的作用看都是一个意思,为了统一叫法,这里统一叫类。
即:
Js中基于对象=js面向对象
Js中没有class,但是取了一个新的名字,原型对象,因此,类==原型对象
●为什么需要对象
问题提出:
张老太养了两只猫,一只名字叫小白,今年3岁,白色,还有一只叫小花,今年10岁,花色。请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色,如果用户输入的小猫名字有误,则显示张老太没有这只猫。
<html>
<head>
<script language="javascript">
/* var cat1_name="小白";
var cat1_age=3;
var cat1_color="白色";
//传统的方法很麻烦,很复杂
*/
//解决的方法,把猫的属性集中,创建一种新的数据类型(原型对象/类)
//用面向对象的方法来解决上面的问题
//这里就是一个猫类
function Cat(){
}
//如果你这样用
Cat();//函数
var cat1 = new Cat();//类
//这时这个cat1就是一个对象(实例)
cat1.name = "小白";
cat1.age=3;
cat1.color="白色";
//从上面的代码我们可以看出
//1、js中的对象属性可以动态添加,你给什么就有什么
//2、属性没有限制
window.alert(cat1.name+cat1.age+cat1.color+cat1.hobby);
//若使用了没有的属性,则给出undefined
</script>
</head>
<body>
</body>
</html>
●js面向(基于)对象编程---类(原型对象)与对象
计算机语言的发展是向接近于人的思维方式演变的,这是一个大趋势。Js引入的面向对象的思想。Js不是纯面向对象的,我们可以认为它是基于面向对象的。
汇编语言【面向机器】
C语言【面向过程】
Java语言【面向对象】
Js【支持面向对象】
●类和实例的关系
●类和对象的区别与联系
1、类是抽象的,概念的,代表一类食物,比如人、猫、
2、对象是具体的,实际的,代表一个具体事物
3、类是对象实例的模板,对象实例是类的一个个体
●类—如何自定义类和对象(5种)
1、工厂方法—使用new Object创建对象并添加相关属性
2、使用构造函数来定义类(原型对象)
3、使用prototype
4、构造函数及原型混合方式
5、动态原型方式
☞先说使用构造函数来定义类,然后再创建对象实例。
基本语法:
Function类名(原型对象名)(){
//私有方法、公开方法等
}
创建对象
Var对象名 = new类名();
现在对对象作特别说明:
▶js中一切都是对象
function Person(){}
var a = new Person();
window.alert(Person.constructor);//类也是对象
window.alert(a.constructor);
window.alert(typeof a);//object
var b = 123;
window.alert(b.constructor);//
window.alert(typeof b);//number
var c = "ad";
window.alert(c.constructor);//
window.alert(typeof c);//number
//思考:如何判断一个对象是不是Person实例?如下:
if(a instanceof Person){
window.alert("a是Person OK1")
}
if(a.constructor == Person){
window.alert("a是Person ok2");
}
▶对象-function对象
类(原型对象)其实也是对象,它实际上是Function类的一个实例,通过类我们可以创建自己的对象实例。
▶补充说明:(带var和不带var的区别)
//全局变量
var abc = 89;
function test(){
abc = 900;
//不带var和不带var是有区别的
// 在函数里,如果不带var则表示使用全局的abc变量
//如果带上var 则表示在函数里面定义了一个新的var变量
}
test();
window.alert(abc);//输出900
●对象实例-如何访问(使用)对象实例的成员变量
▷对象实例名.属性名
▷对象实例名[“属性名”];
对象实例名[“属性名”]的方式可以实现动态访问变量。
function Person(){}
var p1 = new Person();
p1.name = "Gavin";
window.alert(p1.name);
window.alert(p1["name"]);//意义就是实现动态访问
var str = "na"+"me";
window.alert(p1[str]);//通过串访问
▶一个问题:
答案当然是10了;
看下面代码:
function Person(){}
var a = new Person();
a.age =10;
a.name="小明";
var b =a;
b.name = "小白";
window.alert(b.age+"名字"+b.name+" 名字"+a.name);
效果:
对象引用分析图:
●js中垃圾回收机制
如上所示,当堆地址的引用次数为0的时候,可能就要被gc回收了。这取决于gc回收机制。
可能电脑内存不够的时候就被浏览器引擎删掉了。也可能、、、
Js还提供了一种方式,主动释放对象内存。
Delete对象名.属性名 //这样就会立即释放对象的这个属性空间
●this关键字
This问题的提出:
在实际的编程中,我们可能有这样的需求,当我们创建一个对象后,就希望该对象自动拥有某些属性【比如,当我们创建了一个Person对象后,就希望该对象自动拥有某些属性,这该怎么办?】
解决之道:
使用this!
function Person(){
This.name = “abc”;
This.age=19;
}
var p1= new Person();
var p2= new Person();
window.alert(p1.name+” ”+p2.name);
内存分析图:p1和p2是两个不同的对象,指向不同的地址。
▶
//可能大家会这样去思考这个问题
function Person(){
var name ="abc";
var age = 900; //这时候是私有属性
this.name = "Gavin";//这时候为公开的属性
//私有的属性若想访问的话,就要用公开的方法。
this.show=function(){//这个就是Person类的一个方法,公开的(特权方法)
window.alert(name+" "+age); //abc 900
show2();//调用show2方法
}
function show2(){
//这是Person类的私有方法,只能在内部使用。
//在内部是可以访问变量的
window.alert("show2()"+" "+name+" "+age);
//外部使用私有方法可以在公开方法中调用。
}
}
var p1 = new Person();
p1.show();
//window.alert(p1.name+" "+p1.age);
//p1.show2();//这里会报错
●进一步理解this
记住一句话:
哪个对象实例调用this所在的函数,那么this就代表哪个对象实例
案例1:
function test1(){
alert(this.v);//这个函数也是属于window
}
var v = 90;//该属性是属于window的
window.alert(window.v);//该句话等同于window.alert(v)
window.test1();//输出90,当成了函数来用,该函数属于window类
//等价于 test1();
案例2:
function Person(){
this.v="Gavin";
this.abc = function(){
window.alert(this.v);
}
}
var p = new Person();
p.v="hello";
p.abc();
分析图:
function Person(name,age){
//这个就是使用传入的实参去初始化对象的属性。
this.name = name;
this.age = age;
//输出自己的名字,这里this.show就是一个公开的函数,函数名是show
this.show = function(){//没有参数
document.writeln("名字="+this.name);
}//这样去分配函数,是每一个函数都有这么一段代码,很浪费。
this.jisuan=function(n){
var res = 0;
for(var i=0;i<=n;i++){
res+=i;
}
return res;
}
}
var p1 = new Person("宋江",90);
p1.show();
var p2 = new Person("林冲",12);
p2.show();
document.writeln("<br/>res="+p1.jisuan(10));
☞给一个对象添加(指定)函数的方法:
◆第一种
function Person(){
this.name= "abc" ;
this.age= 900;
}
functionshow1(){
window.alert("hello"+this.name);
}
//创建一个对象
varp1 = new Person();
//将show1函数指针给p1
//若写成p1.abc = show1();则是把返回值给abc.
p1.abc= show1;//此时abc就表示一个函数了
p1.abc();//调用,这里加括号
//以下为测试
window.alert(p1.abc);//输出show1函数,如下图:
window.alert(show1);//也是输出show1函数
show1();//只输出hello,因为调用show1方法的是window对象,
//而window没有name属性
◆第二种
//第二种定义函数方法
function Person(){
this.name = "abc";
this.age=900;
}
var p1 = new Person();
p1.abc = function show(){//这里的show也可以去掉
window.alert("hello"+this.name);
};//这里要加分号。不加分号也可以
p1.abc();//调用abc函数
★注意:js函数调用只看 函数名
function Person(){
this.name="abc";
this.age = 900;
this.abc = function(v1,v2){
window.alert(this.name+" "+this.age+" "+v1+" "+v2);
}
}
var p1 = new Person();
p1.abc();//即使没有参数也可以调起来,js是根据函数名调用的,而不看参数
看下面运行结果:因为没有参数,所以这时候的v1和v2是undefined
◆使用另一种方法来给类增加方法。
前面的几种方法有一个问题,就是每个对象独占代码,这样的话如果对象过多,则会影响效率,js设计者给我们提供了另一种方法,原型法:这样对个对象可以共享函数代码,节省空间。
function Dog(){
}
var dog1 = new Dog();
//动态绑定一个函数给shout属性
dog1.shout=function(){
window.alert("小狗");
}
dog1.shout();
var dog2 = new Dog();
//dog2.shout();//这里报错,因为dog2没有shout方法
//希望所有的对象,共享某个函数
Dog.prototype.shout2=function(){//使用prototype去绑定一个函数,是//绑定到类上的所以是所有的对象共享的
window.alert("也是一只狗");
}
dog2.shout2();//正确
window.alert(dog1.shout2==dog2.shout2);//这句话测试两只狗的该方法是//否是同一块代码区,输出为true!
扩展(补讲):双等号(==)的作用
①当等号的两边都是字串的时候,则比较内容想不想等,如果相等则返回true,否则返回false
②如果等号两边是数字,则比较数字的大小。
③若果等号两边是对象或是对象函数,则比较的是地址是否相等。
则:
判断两个对象是否相等,即是否指向同一块内存地址,可以使用双等(==)判断,输出false/true;
对代码的原理分析如下图:
从图上可以看到,这样可以使所有对象共享一块代码区,节省了空间