面向对象
面向对象的初心
- 改善可读性
- 提升重用性
原则:开放封闭原则
- 对于扩展是开放的(Open for extension)。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。
- 对于修改是关闭的(Closed for modification)。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。
目的
三要素:封装、继承、多态
类:上帝创造万物
面向对象可以解释任何事物(哲学?)
生命
p: body
m: born
m: die
动物
m: run
植物
m: 光合作用
猫
m: 上树
m: say
狐狸
m: 成仙
m: say
m: say
编程的时候你就是上帝
Object
p: __proto__
m: toString
m: valueOf
Array
p: length
Function
p: length
m: push
m: call
对象:将类实例化
var object = new Object()
类是图纸
将图纸实现(实例化、放入内存)就是对象
var image = new Image()
var cat = new Cat()
想象上帝创造猫这个类,然后创造一个猫的实例。
小结
- 类可以继承类(父类与子类)
- 将类实例化,就有了对象
- 对象拥有类的属性和方法、父类的属性和方法、父类的父类……
- 将一些属性和方法封装为类
- 多态:不同对象的同一个方法,可以有不同的表现
JavaScript 使用原型链实现继承
Java 使用 类 实现继承
JavaScript 可以模拟 Java 的继承(部分)
class 以前是 JavaScript 的保留字,现在已经是关键字了
预备知识 - new 操作
var object = new Object() 时,发生了什么?
- 创建一个空对象作为 this
- this.__proto__ 指向构造函数的 prototype
- 运行构造函数
- 返回 this(如果构造函数没有 return)
预备知识 - this
this 的值到底是什么?
- 默认情况下,this === window(node 里另说,strict mode 另说)
- 使用 func.call(context, param1) 的第一个参数指定 this
- object.method(param1) 可以指定 method 的 this 为 object
- 相当于 object.method.call(object, param1)
this 的值在函数执行时才能确定
注意区别:变量在定义时就确定
P.S.
- func.call 和 func.apply 的区别
- func.bind(context) 的作用
如何确定 this 的值:
如何手动指定对象的原型
1. object.__proto__ = { ... }
ECMAScript 6 之前没有涉及过 __proto__,只是由于浏览器都实现了 __proto__,ECMAScript 才将 __proto__ 加入到 Specs
2. 借用 new
var myProto = {
name: 'foo'
}
var obj = {}
var Temp = function(){}
Temp.prototype = myProto
obj = new Temp()
3. 使用 Object.create(proto) MDN
JS实现一个构造函数
对应 Java 里面的『类』
var Animal = function(){
this.种类 = '动物'
}
Animal.prototype.say = function(){
console.log(this.种类 + '叫')
}
实例化,得到一个对象
var animal = new Animal()
animal.say()
JS继承一个类
var Cat = function(){
Animal.apply(this, arguments)
this.tail = '一条尾巴'
}
// 下面三句话只是为了实现 Cat.prototype.__proto__ = Animal.prototype
var F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
// 纠正一下 constructor
Cat.prototype.constructor = Cat;
Cat.prototype.run = function(){
console.log('猫儿在跑')
}
Cat.prototype.say = function(){
console.log('喵喵喵')
}
var cat = new Cat()
cat.say()
不用类也能实现继承
var animal = {
'种类':'动物',
say: function(){
console.log('动物叫')
}
}
var cat = Object.create(animal) // 使用任意手段让 cat.__proto__ === animal
cat.tail = ''
cat.say= function(){
console.log('喵喵喵')
}
JS 里面没有事件
区别于 DOM 事件
JS里的事件有什么用?
举例:不同代码块间的通信
数据已更新!
Text
保存
Text
保存
Text
保存
Text
保存
RSS 订阅
用一个例子说明发布订阅模式(观察者模式)
- 读者可以订阅一个博客的 RSS
- 读者可以取消订阅
- 一旦 RSS 更新,读者就会收到提示
- 博客作者可以触发 RSS 更新
一个事件系统长什么样子
- eventSystem.on('xxx', fooFunction)
- eventSystem.trigger('xxx', data)
- eventSystem.off('xxx', fooFunction)
// 用户提交数据完毕后提示用户
// main.js
!(function(){
var notify = function(message){
alert(message)
}
eventSystem.on('submitSuccess', function(message){
notify(message)
})
})()
// a.js
$.post(urlA, function(){
eventSystem.trigger('submitSuccess', '数据A已更新')
})
// b.js
$.post(urlB, function(){
eventSystem.trigger('submitSuccess', '数据B已更新')
})
// c.js
$.post(urlC, function(){
eventSystem.trigger('submitSuccess', '数据C已更新')
})
// foo.js
!(function(){
eventSystem.on('submitSuccess', function(message){
// 做其他事情
})
})()
世上最小的发布订阅系统
(function($) {
var o = $({});
$.on = function() {
o.on.apply(o, arguments);
};
$.off = function() {
o.off.apply(o, arguments);
};
$.trigger = function() {
o.trigger.apply(o, arguments);
};
}(jQuery));
这样的设计用于模块间通信非常方便,所以程序员给它起来一个名字:
发布/订阅模式
被起了名字的常用设计,就叫做设计模式
完
下一课:一些框架的介绍
下下课:写简历与面试的技巧
找工作的同学可以找老师模拟面试(多次)
1. 给我简历
2. 告诉我你的目标职位
3. 约时间模拟面试
面向对象
By 方方
面向对象
- 1,962