一、什么是对象?
对象是包含了属性和方法的集合体
二、什么是面向对象?
面向对象是一种编程思想,在JS当中利用原型来阐述这种思想的编程方法
三、构建对象:
1.内置对象:
String Math Date Array Boolean RegExp
2.自定义对象:
方式一:通过new Object()的方式创建对象
var objwang=new Object(); //指定对象的属性 objwang.name="王洪涛"; objwang.address="北京市海淀区五道口公共厕所"; //指定对象的方法 objwang.show=function(){ alert(objwang.name); }; //调用方法 objwang.show();
方式二:通过字面量创建对象
/*通过字面量创建对象*/ var objliu={ //属性 name:"刘彬", age:25, //方法 say:function(){ alert('大家好,我叫'+this.name+",欢迎大家来到我的烧烤店品尝烧烤,今日的消费由刘磊买单"); } }; //调用方法 objliu.say();
四、构造函数和原型对象
(一)、构造函数
/* 构造函数 */ function Student(name,age){ this.name=name; this.age=age; this.say=function(){ alert(this.name); } };
使用构造函数,必须使用new操作符
var student1=new Student("john",13); var student2=new Student("baby",18);
对象的constructor属性最初是用来标识对象类型的,但是提到检测对象类型,还是instanceof操作符更可靠一些
alert(student1.constructor==Student);//true alert(student1 instanceof Student);//true alert(student1 instanceof Object);//true
(二)、原型对象
1.js创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象
2.prototype就是通过调用构造函数而创建的那个对象实例的原型对象,使用原型对象的好处就是可以让所有对象实例共享它的所有方法和属性
function Flower(){ } Flower.prototype.name="曼陀罗花"; Flower.prototype.genera="茄科 曼陀罗属"; Flower.prototype.area="印度、中国北部"; Flower.prototype.uses="观赏或药用"; Flower.prototype.showName=function() { alert(this.name); } var flower1=new Flower(); flower1.showName(); var flower2=new Flower(); flower2.showName(); alert(flower1.showName==flower2.showName);//true
3.在默认情况下,所有原型对象都会自动获得一个constructor的属性,这个属性包含一个指向prototype属性所在函数的指针。所以Flower.prototype.constructor指向Flower。
4.当调用构造函数创建一个新实例后,该实例的内部将包含一个指针指向构造函数的原型对象,这个属性是_proto_
5.关系图解:(p1和p2中的属性改为_proto_,图中写法有误)
6.当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性
五、继承
(一)、原型链
一个原型对象是另一个原型对象的实例 (Man.prototype=new Humans())相关的原型对象层层递进,就构成了实例与原型的链条,就是原型链
function Humans(){ this.clothing=["trousers","dress","jacket"]; } function Man(){ } //必须先指定父子关系 Man.prototype=new Humans(); var man1=new Man(); man1.clothing.push("coat"); alert(man1.clothing); var man2=new Man(); alert(man2.clothing);
关系图:
原型链存在两个问题:
1.包含引用类型的原型,由于包含引用类型值的原型属性会被所有实例共享,在通过原型来实现继承时,原型实际上会变成另一个类型的实例,因此,原先的实例属性也就变成了原型的属性了;
2.在创建子类型实例时,不能向父类型的构造参数中传递参数
(二)、对象继承
1.借用构造函数:子类型构造函数内部调用父类型构造函数
apply(对象,参数数组);
call(对象,参数列表);
/*创建子类Dog*/ function Dog(name,health){ /* 创建子类型的实例时,父类型的构造函数中传递参数 */ var array=[name,health]; //apply()传递参数时,要把参数封装到数组当中 /* Pet.apply(this,array) */ //call()传递参数,必须把参数列举出来 Pet.call(this,name,health); }
方法只能在构造函数内定义,方法无法复用
2.组合继承(伪经典继承)
原型链和借用构造函数同时使用时称为组合继承
function Humans(name){ this.name=name this.clothing=["trousers","dress","jacket"]; } Humans.prototype.sayName=function(){ alert(this.name) } function Man(name){ Humans.call(this,name);//继承属性 this.age=age; } Man.prototype=new Humans();//继承方法