面向对象程序设计:Object-oriented programming(OOP)
逻辑运算符的知识:
且(&&)运算符
五个falsy 值:(‘’,0,NaN,null,undefined)
&& 运算符返回第一个 falsy 值(停止运算),若无 falsy 值,则返回最后一个 truthy 值
1&&0&&2&&3
//0 也就是这里面的第一个falsy值
console.log(3) && 0
//undfined 并且console.log(3)执行了,因为console.log()的值是undefined,是一个falsy值,所以就返回undefined
0&&console.log(3)
//0 第一个falsy值是0,然后直接返回0,console.log(3)不会执行
或(||)运算符
- 如果运算表达式里的值里有除falsy值以外的值
那么就返回第一个真值
如:
0||1||null
//1 因为1不是falsy值
- 如果运算表达式里的值全是falsy值,那么返回最后一个falsy值
如:
0||''||null
//null
|| 运算符返回第一个 truthy 值(停止运算),若无 truthy 值,则返回最后一个 falsy 值
使用全局变量时给一个变量赋值要注意的问题
var app = {}
//危险代码 如果之前有人声明了一个全局app变量,你这样直接写会覆盖之前的
正确写法:
var app = app || {}
//就相当于
If(app){
app = app
}else{
app = {}
}
上面的代码的意思是如果全局变量app这个变量存在,那么全局变量app就等于之前存在的那个变量app,否则app就等于一个空对象
命名空间
var app = app || {}
就是全局命名空间
之后所有的方法和属性都可以写在app上面,app就像一个房间一样装这所有的属性和方法,所以叫做命名空间
比如:
app.event= {}
app.commonMethod = {
Name: ‘’,
Age: ‘’
}
app.init= function(){}
另外我们的文件夹也相当于一个命名空间
构造函数:constructor(类:class)
JavaScript 基于原型,没有类的概念;但是我们可以定义一个类
下面代码就是一个新的类 Person
function Person() { }
// 或
var Person = function(){ }
JavaScript 中类的本质是函数,只是它有两个特点:
1.函数体内部使用了this关键字,代表了所要生成的对象实例。
2.生成对象的时候,必须使用new命令
这两个特点就形成了所谓的构造函数
为了与普通函数区别,构造函数名字的第一个字母通常大写,如这里的Person
对象(类的实例)
function Person() { }
var person1 = new Person();
var person2 = new Person();
以 Person 为类(模版),person1 和 person2 是 Person 新的实例:person1、person2 可以调用函数 Person
为什么会有面向对象编程?
写了一个 person1 ,又写了一个 person2 ,然后又写了一个 person3 。。。
它们有很多重复的代码:这些代码结构一致(如我们之前的 MVC 设计模式,简直浪费内存(内存条那么贵)
于是就有了 Person 这个构造函数作为对象的模板:把所有相同结构的代码用一个函数封装起来
可以让 person1 等只需要用 new 的方法调用这个 Person 传入参数来使用它的模版,person1 自身属性,再单独罗列即可
原来代码
! function () {
// MVC 的 V
var view = document.querySelector('section.message')
//添加 M
var model = {
init: function () {
var APP_ID = '2zeITbbU6cgHT0mdBscQtmp0-gzGzoHsz'
var APP_KEY = 'iByF5Dy55tJodAoxC4cxwAwx'
AV.init({
appId: APP_ID,
appKey: APP_KEY
})
},
//获取所有数据
fetch: function () {
var query = new AV.Query('Message')
return query.find() //Promise 对象
},
//创建数据
save: function (name,content) {
var Message = AV.Object.extend('Message');
var message = new Message();
return message.save({ //Promise 对象
name: name,
content: content
})
}
}
// MVC 的 C
var controller = {
view: null,
model: null,
messageList: null,
init: function (view, model) {
this.view = view
this.model = model
this.messageList = view.querySelector('#messageList')
this.form = view.querySelector('form')
this.model.init()
this.loadMessages()
this.bindEvents()
},
loadMessages: function () {
this.model.fetch().then((messages) => {
let array = messages.map((item) => item.attributes)
array.forEach((item) => {
let li = document.createElement('li')
li.innerText = `${item.name} : ${item.content}`
this.messageList.appendChild(li)
})
})
},
bindEvents: function () {
this.form.addEventListener('submit', (e) => {
e.preventDefault()
this.saveMessage()
})
},
saveMessage: function () {
let myForm = this.form
let content = myForm.querySelector('input[name=content]').value
let name = myForm.querySelector('input[name=name]').value
this.model.save(name, content).then(function (object) {
let li = document.createElement('li')
li.innerText = `${object.attributes.name} : ${object.attributes.content}`
let messageList = document.querySelector('#messageList')
messageList.appendChild(li)
myForm.querySelector('input[name=content]').value = ''
console.log(object)
})
}
}
controller.init(view, model)
}.call()
把 M、V、C 三个模版单独分出
M 的模版
// Model 办事,我放心
// 通过全局函数 window 引入 Model 便于所有 model 调用
// 提供三个参数:Options、resourceName 和 object
window.Model = function (Options) {
let resourceName = Options.resourceName
return {
init: function () {
var APP_ID = '2zeITbbU6cgHT0mdBscQtmp0-gzGzoHsz'
var APP_KEY = 'iByF5Dy55tJodAoxC4cxwAwx'
AV.init({
appId: APP_ID,
appKey: APP_KEY
})
},
fetch: function () {
var query = new AV.Query(resourceName)
return query.find()
},
//创建数据
save: function (object) {
var X = AV.Object.extend(resourceName)
var x = new X();
return x.save(object)
}
}
}
V 就比较简单了,就一句话,但是封装后也可以调用以便减少代码
window.View = function(Selector){
return document.querySelector(Selector)
}
这里 C 是有一定难的,需要对 this 的概念有所理解
window.Controller = function (options) {
var init = options.init //这个 init 就是 controller 传进来的,记为 initB
// 4-21 return 一个 object
let object = {
view: null,
model: null,
init: function (view, model) { // 注意这里的 init 是 object 的属性,记为 initA
this.view = view
this.model = model
this.model.init()
// 3.initB.call(this)
init.call(this, view, model) // 这里的 init 当然是 initB,写成这样 init(view,model) 你就懂了
this.bindEvents.call(this)
},
}
// 把除 init 外的所有 options 的参数传给 object
// init 是公共参数,而其他实例独有的参数需要传进来
for (let key in options) {
if (key !== 'init') {
object[key] = options[key]
}
}
return object
}
现在可以直接调用 M、V、C 了,其他实例也是一样的
! function () {
// MVC 的 V
// 这里 window.View 的 window 可以省略,是默认的
var view = View('section.message')
//添加 M
var model = Model({
resourceName: 'Message'
})
// MVC 的 C
// 1.controller === object
var controller = Controller({
init: function () {
this.messageList = view.querySelector('#messageList')
this.form = view.querySelector('form')
this.loadMessages()
// 这里的 this 是 object,但是 object 没有上面参数
// 所以才要 for...in...遍历一下,让 object 有这些 controller 独有的参数
},
loadMessages: function () {
this.model.fetch().then((messages) => {
let array = messages.map((item) => item.attributes)
array.forEach((item) => {
let li = document.createElement('li')
li.innerText = `${item.name} : ${item.content}`
this.messageList.appendChild(li)
})
})
},
bindEvents: function () {
this.form.addEventListener('submit', (e) => {
e.preventDefault()
this.saveMessage()
})
},
saveMessage: function () {
let myForm = this.form
let content = myForm.querySelector('input[name=content]').value
let name = myForm.querySelector('input[name=name]').value
this.model.save({
name: name,
content: content
}).then(function (object) {
let li = document.createElement('li')
li.innerText = `${object.attributes.name} : ${object.attributes.content}`
let messageList = document.querySelector('#messageList')
messageList.appendChild(li)
myForm.querySelector('input[name=content]').value = ''
console.log(object)
})
}
})
// 2.controller.init(view, model)
controller.init(view, model)
}.call()
关于 this
1.controller === object
2.controller.init(view, model)
写成 call 的形式:controller.init.call(controller, view, model)
// MDN 里 this 文档告诉我们:this 是 call 的第一个参数
显然 controller.init 里面的 this 当然是 controller
那它还是 object:即 controller.init 里面的 this 就是 object
相当于 object.init 里面的 this 是 object
3.initB.call(this)
initB 里面的 this === call 后面的this
call 后面 this === 第二条里的 this
第二条里面的 this === object
=> initB 里面的 this 就是 object
网友评论