review javascript 24:面向对象
(1)知识点
- (1.1)定义
- (1.2)创建对象
- (1.3)原型与原型链
- (1.4)特点
(2)细化
(2.1)定义
对象:程序中描述一个现实中具体事物的属性和方法的结构
比如汽车是一个对象,车的品牌,颜色就是属性;启动,停止,加速,双闪,刹车都是车子的方法
面向对象:面向对象编程中,描述一个具体事物都需要用对象来封装对象的属性和方法
比如:rest软件架构中,都是按照对象的模块进行划分,比如人员管理,资源管理
/user/id1234
写任何程序,都要先找对象,再识别对象的属性和功能
(2.2)创建对象
(a)json对象
var obj = {"属性名":"值","属性名":"值",...};
(b)定义一个空的对象:
var obj = new Object();
var obj = {};
(c)定义function
定义一个构造函数:
function 类型名(属性参数列表) {
this.属性名 = 参数值;
this.属性名 = 参数值;
this.方法名 = function () {
......
}
}
用new调用构造函数,装饰一个新创建的对象:
var obj = new 类型名(属性值,... ...);
(2.3)原型与原型链
link:http://www.jianshu.com/p/1526fcdc4466
(2.4)特点
面向对象三大特点:【封装】、【继承】、【多态】;
多态又包括重写和重载;
封装
将描述一个事物的属性和方法集中定义在一个对象中。
原因:
1.单独的属性和方法是没有意义的,只有放在对象上才有意义;
2.便于反复调用——代码重用!便于维护!参考下面的例子Car();
继承
inherit父对象中的属性和方法,子对象可直接使用!
原因:代码重用;便于维护;节约内存空间。
Tips:js中的继承都是用 __proto__
那如何修改继承呢?参考资料,总结四种修改继承的方法:
- 仅修改一个对象的父对象:
子对象.__proto__ = 父对象;
Object.setPrototypeOf(子对象,父对象);
-
替换构造函数的原型对象(prototype)为新父对象
结果:将来再创建的子对象,所有新创建的子对象都继承新父对象
时机:在刚刚定义完构造函数后,立刻修改!在修改原prototype对象和创建新子对象之前
步骤:
(a)构造函数.prototype = 新父对象
(b)构造函数.prototype.constructor = 构造函数对象 -
用一个已有的父对象作为参照,创建一个新子对象,同时,扩展子对象自有属性。
在创建一个子对象时,希望随意扩展子对象的自有属性时,使用该继承方法。
var son = Object.create(父对象);
两件事:
a. 创建空对象son
b. 设置son的__proto__指向父对象
var son = Object.create(父对象, {
扩展属性名1: {
writable: true,
value: 属性值,
configurable: true
},
扩展属性名2: {
...
}
});
(上面的1,2,3方式的实例可以参见例2)
- 推荐的继承方式:既继承结构,又继承原型
何时使用:两种类型间的继承
使用:
a. 子类型构造函数开始位置,借用父类型构造函数:
父类型构造函数.call(this,参数列表)
父类型构造函数.apply(this,[参数列表])
Tips:仅完成第一步,只是借用构造函数中的语句而已,没有实现任何对象间的继承
b. 定义构造函数后,设置子类型构造函数的prototype继承父类型的prototype:
Object.setPrototypeOf(子类型.prototype,父类型.prototype)
(4方式的实例可以参见例3)
(3)实践
例1:
<script type="text/javascript">
init();
function init() {
var obj = {name: 'panhf', age: 28};
// hash数组,传入的key必须是字符串
console.log(obj["name"]);
console.log(obj["age"]);
// in
for (var key in obj) {
console.log(key + ":" + obj[key]);
}
var obj1 = new Object();
obj1.name = "zjl";
obj1["age"] = 4;
// 将对象转换成字符串
console.log(JSON.stringify(obj1));
var car = new Car("white", "buick");
var car2 = new Car("black", "benz");
console.log(JSON.stringify(car));
car.launch();
car.stop();
// 原型的使用
Car.prototype.info = function () {
console.log(JSON.stringify(this));
};
console.log("=====");
car.info();
car2.info();
console.log("=====");
/**
*
* 使用jquery加载json文件
*/
var dataroot = "../json/test.json";
var carArr = new Array();
/**
* 异步执行
* http://www.cnblogs.com/chenxizhang/archive/2009/07/02/1515151.html
*
*/
$.getJSON(dataroot, {}, function (data) {
//console.log(data);
for (var i = 0; i < data.length; i++) {
var car = new Car(data[i].color, data[i]["brand"]);
carArr.push(car);
}
//console.log(JSON.stringify(carArr));
});
console.log("=====");
console.log(new Person("phf"));
console.log(new Person("phf", 28));
}
function Person() {
/**
* 参数列表封装在arguments内置对象数组中
*/
console.log(JSON.stringify(arguments));
}
function Car(color, brand) {
this.color = color;
this.brand = brand;
this.launch = function () {
console.log("car is launch");
};
this.stop = function () {
console.log("car is stop");
}
}
function Car(color, brand, createDate) {
this.color = color;
this.brand = brand;
this.createDate = createDate;
this.launch = function () {
console.log("car is launch");
};
this.stop = function () {
console.log("car is stop");
}
}
</script>
例2:
<script type="text/javascript">
/**
* 修改继承的方法
* (1)仅修改一个对象的父对象
* (2)替换构造函数的原型对象(prototype),为新父对象
* (3)用一个已有的父对象作为参照,创建一个新子对象,同时,扩展子对象自有属性
*/
var father = {balance: 100, car: "=B="};
var son = Object.create(father, {//修改继承方法三,用一个已有的父对象作为参照,创建一个新子对象,同时,扩展子对象自有属性
favorite: {value: "坑爹"/*,writable:true*/}
});
console.log(son.balance);//100
console.log(son.favorite);//坑爹
console.log(son.hasOwnProperty("favorite"));//true//自由属性
son.favorite = "飙车";
console.log(son.favorite);//坑爹
function Student(sname, sage) {//this-->刚创建的空对象
this.sname = sname;
this.sage = sage;
}//prototype-->Student.prototype
Student.prototype = father; //(1)修改继承方法二
Student.prototype.constructor = Student;//(2)修改继承方法二
//prototype-->father
//凡是子对象共有的属性值和方法,都要放在构造函数的原型中
Student.prototype.intrSelf = function () {
console.log("I'm " + this.sname + ",I'm " + this.sage);
}//prototype.intrSelf
//father.intrSelf
var lilei = new Student("Li Lei", 18);
var hmm = new Student("Han Meimei", 19);
/*仅修改一个子对象的父对象*/
//hmm.__proto__=father; //(1)修改继承方法一
//Object.setPrototypeOf(hmm,father);//(2)修改继承方法一
console.log(hmm.balance); //100
console.log(lilei.balance);//100
lilei.intrSelf();//I'm Li Lei,I'm 18
hmm.intrSelf();//I'm Han Meimei,I'm 19
</script>
例3:
<script type="text/javascript">
/**
* 修改继承的方法
* 用于两种类型间的继承
*/
//定义所有飞行物类型的构造函数
function Flyer(fname, speed) {
this.fname = fname;
this.speed = speed;
}
Flyer.prototype.fly = function () {//所有飞行物都能飞行
console.log(this.fname + " 以 " + this.speed + " 时速飞行");
};
var bird = new Flyer("小麻雀", 60);
bird.fly();//小麻雀 以 60 时速飞行
/*定义飞机类型的构造函数:名称,速度,载客数*/
function Plane(fname, speed, capacity) {
Flyer.call(this, fname, speed);//——借用构造函数
// this.fname = fname;
// this.speed = speed;
this.capacity = capacity;
}
//Plane.prototype 继承 Flyer.prototype
Object.setPrototypeOf(Plane.prototype, Flyer.prototype);
var A380 = new Plane("A380", 1000, 555);
A380.fly();
Plane.prototype.fly = function () {
console.log(this.fname + " 搭载 " +
this.capacity + " 名乘客以 " +
this.speed + " 时速飞行");
}
A380.fly();//A380 搭载 555 名乘客以 1000 时速飞行
</script>