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 = namethis.age = age}Father.prototype.money = function(){console.log('一个小目标')} // 子类构造函数function Son(name, age){this.name = namethis.age = age} Son.prototype = Father.prototypeSon.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 = namethis.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 = namethis.age = agethis.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 = namethis.age = agethis.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 = namethis.age = age}money(){console.log('一个小目标')}}class Son extends Father {constructor(name, age, sex){// super(name, age) 其实就是借用构造函数继承super(name, age, sex)this.sex = sexthis.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.nameconsole.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] = valuecallback && 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 = valuerender(target)}}) Object.defineProperty(target, 'age', {get(){return setObj.age},set(value){setObj.age = valuerender(target)}})function render(target){document.querySelector('h1').innerHTML = `大家好,我就是曾经江湖中的传说,${target.name}, 他的年龄是:${target.age} `}render(target)