day29
一、函数柯里化
又译为卡瑞化或加里化 是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数 并且返回接受余下的参数而且返回结果的新函数的技术 作用: 可以固定相同参数,实现函数调用传参的简单化 可以让参数复用
1.输出一个完整的url地址:一定要把不变的参数放在第一位
function printUrl(protocol){ return function(domain){ return function(port){ return protocol + domain + port } } } let result = printUrl('https://') let url1 = result('www.baidu.com')(':8080') let url2 = result('www.jd.com')(':6666') console.log(url1) console.log(url2)
2.假设你是一个商家,要出售商品,为了卖出去更多的商品,今天决定打9折进行售卖,我们可以使用以下函数进行折扣后的售出价格计算
function discPrice(disc){ return function(price){ return price * disc } } let result = discPrice(.8) let price1 = result(1000) let price2 = result(2000) console.log(price1) console.log(price2)
二、原型继承
继承是把一个构造函数的属性和方法继承到另一个构造函数里面,而继承必须是同类之间的继承。
原型继承:利用了原型链的规则来实现继承
1.
// 父类构造函数 function Father(name, age){ this.name = name this.age = age } Father.prototype.money = function(){ console.log('一个小目标') } // 子类构造函数 function Son(name, age){ this.name = name this.age = age } Son.prototype = Father.prototype Son.prototype.love = function(){ console.log('谈恋爱') } let s1 = new Son('张三', 18) s1.money() s1.love() let f1 = new Father('张', 36) f1.money() f1.love() console.log(Father.prototype, Son.prototype)
2.
// 父类构造函数 function Father(name, age){ this.name = name this.age = age } Father.prototype.money = function(){ console.log('一个小目标') } // 子类构造函数 function Son(name, age){ // this.name = name // this.age = age } // 把父元素的实例化对象赋值给子类的原型对象了 Son.prototype = new Father('张三', 18) Son.prototype.love = function(){ console.log('谈恋爱') } let s1 = new Son() s1.money() s1.love() console.log(s1.name, s1.age)
三、继承
1.借用构造函数继承
// 父类构造函数 function Father(name, age){ this.name = name this.age = age this.say = function(){ console.log('hello') } console.log('-------', this) } Father.prototype.money = function(){ console.log('一个小目标') } // 子类构造函数 function Son(name, age){ // 借用构造函数继承 Father.call(this, name, age) } let s = new Son('张三', 18) console.log(s)
2.组合继承
// 父类构造函数 function Father(name, age){ this.name = name this.age = age this.say = function(){ console.log('hello') } } Father.prototype.money = function(){ console.log('一个小目标') } // 子类构造函数 function Son(name, age){ // 借用构造函数继承 Father.call(this, name, age) } Son.prototype = new Father() let s = new Son('张三', 18) console.log(s) s.money()
3.ES6继承
// ES6继承原理还是组合继承 class Father { constructor(name, age){ this.name = name this.age = age } money(){ console.log('一个小目标') } } class Son extends Father { constructor(name, age, sex){ // super(name, age) 其实就是借用构造函数继承 super(name, age, sex) this.sex = sex this.init() } init(){ console.log('初始化方法') } } let s = new Son('张三', 18, '男') console.log(s) s.money() console.log(Son.prototype)
四、拷贝
1.浅拷贝 对象的复制只是复制对象的引用,可以改变原始数据的值。 基本数据类型拷贝过去是直接拷贝,而引用数据类型拷贝则拷贝的是地址
let obj = { name: '张三', age: 18, like: ['篮球', 'rap', '剧本杀'] } let obj2 = {} for(let key in obj){ obj2[key] = obj[key] } obj2.like[0] = '唱歌' obj2.name = '张' console.log(obj, obj2)
2.深拷贝(直接修改可能会造成隐性问题,深拷贝能帮你更安全安心的去操作数据,根据实际情况来使用深拷贝) 彻底复制一个对象,而不是简单的拷贝对象的引用,拷贝后不能修改原始数据的值 只有基本数据类型可以完全拷贝,拷贝的不是地址。因此利于这个规则实现深拷贝
let obj = { name: '张三', age: 18, like: ['篮球', 'rap', '剧本杀'] } let obj2 = JSON.parse(JSON.stringify(obj)) obj2.like[0] = '🎤' console.log(obj, obj2)
五、数据劫持(对对象的限定)
1.Object.defineProperty()
参数:=> 参数1表示那个对象需要劫持
=> 参数2表示的是设置那个属性
=> 参数3表示的是对这个属性的限定(配置项,类型是一个对象)
let obj = { name: '张', age: 18, sex: '男' } console.log(obj.name) for(let key in obj){ console.log(obj[key]) } delete obj.name console.log(obj)
注意点:被劫持的对象,通过劫持的方式设置的属性和值,为了做区分,当咱们打印查看结果时,劫持设置的值你是看不到,会默认放在一个括号里面
2.配置项:=> value: 该属性对应的值, => configurable 该属性是否能被删除 => writable: 该属性时候可被重写, 默认是 false => emunerable: 该属性是否可被枚举(遍历), 默认是 false => get: 是一个函数, 叫做 getter 获取器, 可以来决定该属性的值 -> get 函数的返回值, 就是当前这个属性的值 -> 注意: 不能和 value 和 writable 一起使用, 会报错 => set: 是一个函数, 叫做 setter 设置器, 当你需要修改该属性的值的时候, 会触发该函数
let obj = { age: 18, sex: '男' } Object.defineProperty(obj, 'name', { value: '陈', configurable: false, writable: false, enumerable: false }) // delete obj.name // obj.name = '张' for(let key in obj){ console.log(obj[key]) } // console.log(obj)
3.get和set:
let obj = { age: 18, sex: '男' } let _name = 'hello' Object.defineProperty(obj, 'name', { // 获取器,肯定是先有值,才能获取 get(){ console.log('我的属性被获取了') return _name }, set(value){ console.log('我的属性被修改了') _name = value } }) console.log(obj.name) obj.name = '' console.log(obj.name)
4.
// 目标对象,要被劫持的目标对象 let target = {} // 专门用来设置属性的对象,它的作用和刚才那个_name全局变量的作用是一样的 let setObj = { name: '陶', age: 18 } Object.defineProperty(target, 'name', { get(){ console.log('我的属性被获取了') return setObj.name }, set(value){ console.log('我的属性被修改了') setObj.name = value } }) Object.defineProperty(target, 'age', { get(){ console.log('我的属性被获取了') return setObj.age }, set(value){ console.log('我的属性被修改了') setObj.age = value } }) console.log(target.name) target.name = '张' console.log(target.name) console.log(target)
5.封装
let setObj = { name: '', age: 18, sex: '男' } // 参数1表示给目标对象设置值的对象 // 参数2表示回调函数 function reactive(setObj, callback){ let target = {} for(let key in setObj){ Object.defineProperty(target, key, { get(){ return setObj[key] }, set(value){ setObj[key] = value // if(callback){ // callback(target) // } // 优雅的写法,利于短路运算符 callback && callback(target) } }) } return target } let result = reactive(setObj, render) function render(result){ document.querySelector('h1').innerHTML = `大家好,我就是曾经江湖中的传说,${result.name}, 他的年龄是:${result.age},他的性别是:${result.sex} ` } render(result)
6.数据劫持升级
let setObj = { name: '张', age: 18 } // Object.defineProperty() let target = {} Object.defineProperties(target, { 'name': { get(){ return setObj.name }, set(value){ setObj.name = value } }, 'age': { get(){ return setObj.age }, set(value){ setObj.age = value } } }) console.log(target)
7.ES6_Proxy
let setObj = { name: '张三', age: 18, sex: '女' } function reactive(data, callback){ return new Proxy(data, { get(target, property){ return target[property] }, set(target, property, value){ target[property] = value callback && callback(target) } }) } let result = reactive(setObj, render) function render(result){ document.querySelector('h1').innerHTML = `大家好,我就是曾经江湖中的传说,${result.name}, 他的年龄是:${result.age},他的性别是:${result.sex} ` } render(result) console.log(result)
六、响应式数据(数据改变,界面跟着变)
let setObj = { name: '张', age: 18 } let target = {} Object.defineProperty(target, 'name', { get(){ return setObj.name }, set(value){ setObj.name = value render(target) } }) Object.defineProperty(target, 'age', { get(){ return setObj.age }, set(value){ setObj.age = value render(target) } }) function render(target){ document.querySelector('h1').innerHTML = `大家好,我就是曾经江湖中的传说,${target.name}, 他的年龄是:${target.age} ` } render(target)