美文网首页
面向对象编程初探

面向对象编程初探

作者: lyp82nkl | 来源:发表于2019-06-26 00:03 被阅读0次

    面向对象程序设计: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)不会执行
    

    或(||)运算符

    1. 如果运算表达式里的值里有除falsy值以外的值
      那么就返回第一个真值
      如:
    0||1||null
    //1  因为1不是falsy值
    
    1. 如果运算表达式里的值全是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
    

    相关文章

      网友评论

          本文标题:面向对象编程初探

          本文链接:https://www.haomeiwen.com/subject/cvmfcctx.html