mvvm和函数柯里化

MVVM架构模式和函数柯里化

1.MVVM架构模式

2.函数柯里化

01-MVVM架构模式【重点】

`概念`MVVM是一种架构/设计模式。 MVVM是Model,View和ViewModel的简称

	Model: 模型层。 提供数据
    View: 视图层。 渲染页面
    ViewModel: 视图模型层 连接模型层和视图层的桥梁
    
 `核心`:实现了数据的双向绑定。数据驱动视图:当数据发生变化,视图会自动更新。
 
 `Object.defineProperty()实现MVVM架构`:
  <div id="app"></div>

    <script>
        // MVVM核心:数据的双向绑定,数据驱动视图

        // Model: 模型层  提供数据
        var model = {
            uname: '小妲己'
        }

        // ViewModel: 视图模型层  连接模型层和视图层
        /* 
            考虑:1. 什么时候访问了数据;2. 什么时候更新了数据
        */
        // 数据劫持
        var _uname = model.uname
        Object.defineProperty(model, 'uname', {
            get: function () {
                // 当访问了被监听的属性时触发
                console.log(new Date(), 'uname属性被访问了');
                // 注意:这里不能返回被监听的属性,否则会一直触发get方法,变成死循环
                // 解决:可以在劫持之前,将被监听的属性赋值给另一个临时变量
                return _uname
            },
            set: function (newVal) {
                // 当修改了被监听的属性时触发
                console.log(new Date(), 'uname属性被修改了', newVal);
                // 修改模型层的数据
                _uname = newVal
                // 通知视图层更新
                watch()
            }
        })


        // View: 视图层 渲染页面
        function render() {
            app.innerHTML = `<span>${model.uname}</span><button οnclick="changeUname()">戳我呀~</button>`
        }

        render()

        function changeUname() {
            // 修改了被监听的属性,会触发set方法
            model.uname = '小貂蝉'
        }

        function watch() {
            render()
        }
        // Object.defineProperty是一个es5方法
        // Object.defineProperty(劫持的对象, '监听的属性', {
        //     get: function () {
        //         // 当访问了被监听的属性时触发
        //     },
        //     set: function () {
        //         // 当修改了被监听的属性时触发
        //     }
        // })
    </script>


`Proxy实现MVVM架构`<div id="app"></div>

    <script>
        // Model: 数据层。 提供数据
        var model = {
            uname: '小妲己',
            age: 18
        }
        // ViewModel: 数据模型层, 连接数据层和视图层的桥梁
        var newModel = new Proxy(model, {
            get: function (target, key) {
                console.log(target, key);
                // 访问了被监听的对象属性时触发
                console.log(new Date(), '访问了被监听的对象属性');
                return target[key]
            },
            set: function (target, key, newVal) {
                console.log(target, key, newVal);
                // 修改了被监听的对象属性时触发
                console.log(new Date(), '修改了被监听的对象属性');
                // 修改了视图模型层的数据
                target[key] = newVal
                // 通知视图更新
                watch()
            }
        })

        // View: 视图层. 渲染页面
        function render() {
            app.innerHTML = `<span>${newModel.uname}</span><span>${newModel.age}</span><button οnclick="changeUname()">戳我呀~</button>`
        }

        render()

        // 用户的交互行为
        function changeUname() {
            newModel.uname = '小貂蝉'
            newModel.age = 19
        }

        function watch() {
            render()
        }

        // Proxy: es6的数据代理, 是一个构造函数。可以监听整个对象的任意属性的访问或者修改
        // new Proxy(代理的对象, {
        //     get: function (target, key) {
                    // target: 被监听的对象;
                    // key: 被监听的对象的属性
        //         // 访问被监听的对象属性时触发
        //     },
        //     set: function (target, key, newVal) {
                    // target: 被监听的对象;
                    // key: 被监听的对象的属性
                    // newVal: 修改的属性值
        //         // 修改被监听的对象属性时触发
        //     }
        // })
    </script>

02-Object.defineProperty()

`概念`:es5中一个用来实现数据劫持的方法,具有唯一性:es5没有其他方法可以替代

`问题`: Object.defineProperty这个方法自身具有一些缺陷

`解决`: es6 Proxy 数据代理

`语法`: Object.defineProperty(劫持的对象, '监听的属性', {
    get: function() {
        // 访问了被监听的对象的属性时触发
    },
    set: function(newVal) {
        // 修改了被监听的对象的属性时触发
    }
})

03-Proxy

`概念`: es6中一个用来实现数据代理的方法。 

`特点`: 可以监听整个对象任意属性的访问和修改

`语法`let newModel = new Proxy(代理的对象, {
    get: function(target, key) {
        // 访问了对象的属性时触发
    },
    set: function(target, key, newVal) {
        // 修改了对象的任意属性时触发
    }
})

04-Object相关的静态方法

# Object.create(): 创建一个新的对象,新对象的隐式原型会指向源对象

# Object.assign(): 合并对象|浅拷贝

# Object.defineProperty(): 数据劫持

# Object.keys(): 遍历对象,并返回对象的属性名组成的数组

# Object.values(): 遍历对象,并返回对象的属性值组成的数组

05-hasOwnProperty

`作用`: 判断当前对象中是否有指定的属性,不包含原型上的属性。返回布尔值

let obj = {
    uname: '小妲己',
    age: 18,
    sex: '女'
}

Object.prototype.add1 = '立人科技'

// obj就是Object构造函数的实例对象,自然可以访问Object构造函数原型对象上的属性和方法
console.log(obj.add1); // 立人科技

// 注意:hasOwnProperty这个方法用来判断某个值是否是对象自身的属性,不包含原型对象上的属性

console.log(obj.hasOwnProperty('age')); // true

console.log(obj.hasOwnProperty('hobby')); // false

console.log(obj.hasOwnProperty('add1')); // false

06-函数柯里化【面试题】

`概念`'官方解释'在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术

'理解': 把原本接收所有参数的函数转换成只接收部分参数的函数,并且返回一个新函数,这个新函数可以接收剩余参数,并返回最终的结果

`特性`1. 参数的延迟调用; 2. 参数复用

`示例代码`// 注意:递归的使用场景:需要使用重复的代码的时候,但是并不确定要使用多少次的时候

// 功能:计算任意个数的数字的累加和
function currySum() {
    // console.log(arguments);
    let args = [...arguments] // 将伪数组转换为真数组
    let inner = function () {
        if (arguments.length === 0) { // 执行到了末尾,就可以计算累加和
            return args.reduce((pre, cur) => pre + cur)
        } else {
            // 没有执行到末尾,将新的一个小括号的数字添加到数组中
            args.push(...arguments)
            // 并且要返回inner函数
            return inner
        }
        // args.push(...arguments)
        // return args.reduce((pre, cur) => pre + cur)
    }
    return inner
}

// console.log(currySum(2)(3));
console.log(currySum(2)(3)(4)());
console.log(currySum(2)(3)(4)(5)());
console.log(currySum(2)(3)(4)(5)());
console.log(currySum(2)(3)(4)(5)(6)());
console.log(currySum(2)(3)(4, 3, 1)(5)(6, 10, 2)(7)());

 // 利用函数柯里化的特性:参数复用。实现了url地址拼接的功能

function uri(protocol) {
    return function (hostname, path) {
        return `${protocol}${hostname}${path}`
    }
}

let curryUri = uri('https://') // 每一次拼接的时候,就只需要调用一次'protocol'这个属性

console.log(curryUri('www.baidu.com/', 'index.html'));
console.log(curryUri('www.sina.com/', 'about.html'));

扩展

        闭包:跨作用域调用函数

        递归使用场景:需要使用重复的代码的时候,但是不知道使用多少次。函数直接或者间接调用自己,自己调用自己就是递归函数

        回调函数:函数内部(自己)调用(自己的)参数传过来的函数
        
        函数调用:函数内部调用其他函数
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值