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)
二、原型继承
继承是把一个构造函数的属性和方法继承到另一个构造函数里面,而继承必须是同类之间的继承。
原型继承:利用了原型链的规则来实现继承
// 父类构造函数
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)
// 父类构造函数
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)
// 目标对象,要被劫持的目标对象
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)