一.ES6继承
class Person {
// 当我们没有在类里面写构造函数时,编译器会自动增加一个空的constructor函数。
eat() {
console.log("eat");
}
}
class Doctor extends Person {
// 当我们在子类里没有写构造函数时,编译器会自动增加一个constructor函数,并且,在constructor函数里调用super();
seatZhen() {
console.log("seatZhen");
}
}
let p1 = new Person();
p1.eat();//eat
let d1 = new Doctor();
d1.eat();//eat
d1.seatZhen();//seatZhen
二.单例模式(ES5)
// 单例模式:某个类只能创建一个实例。
// ES5的写法:
let singleton = (function () {
function Map(width, height) {
this.width = width;
this.height = height;
}
let instance;//保存Map的对象(实例)
return {
getInstance: function (w, h) {
if (instance == undefined) {
instance = new Map(w, h);
} else {
instance.width = w;
instance.height = h;
// Map.call(instance,w,h);
}
return instance;
}
}
})()
// 定义一个Map的实例。
let m1 = singleton.getInstance(100, 200);
let m2 = singleton.getInstance(300, 400);
console.log("m1", m1);//m1 Map {width: 300, height: 400}
console.log("m2", m2);//m2Map {width: 300, height: 400}
m2.width = 500;
console.log("m1", m1);//m1 Map {width: 300, height: 400}
console.log("m2", m2);//m2 Map {width: 300, height: 400}
console.log(m1 === m2);//true
三.单例模式(ES6)
// 单例模式:某个类只能创建一个实例。
// ES6的写法:
let singleton = (function () {
class Map {
constructor(width, height) {
this.width = width;
this.height = height;
}
}
let instance;//保存Map的对象(实例)
return {
getInstance: function (w, h) {
if (instance == undefined) {
instance = new Map(w, h);
} else {
instance.width = w;
instance.height = h;
// Map.call(instance,w,h);
}
return instance;
}
}
})()
// 定义一个Map的实例。
let m1 = singleton.getInstance(100, 200);
let m2 = singleton.getInstance(300, 400);
console.log("m1", m1);
console.log("m2", m2);
m2.width = 500;
console.log("m1", m1);
console.log("m2", m2);
console.log(m1 === m2);
四.观察者模式(发布订阅)
五.Object.defineProperty和发布订阅模式结合实现Vue的响应式原理
六.柯里化的终极解决方案
function sum(a, b, c, d) {
return a + b + c + d;
}
// 把sum(a,b,c,d)转成 sum(a)(b)(c)(d);
function curry(cb, arr = []) {
return function (...args) {
let arrs = [...arr, ...args];
if (arrs.length < cb.length) {//判断实参个数是否和原函数的形参个数的关系
return curry.call(this, cb, arrs)//调用闭包时,传入arrs,把前面调用的状态进行保持。
} else {
return cb(...arrs);
}
}
}
let sfn = curry(sum);
let onefn01 = sfn(2);
// let onefn02 = onefn01(3);
// console.log(onefn01 == onefn02);//false
// let add23 = sfn(2)(3);
// console.log(add23(4, 5));//14
// console.log(add23(5, 6));//16
function curry2(cb) {
let arrs = [];//[1,2,3,4]
function fn(...args) {
arrs = [...arrs, ...args];//[1,2,3,4]
if (arrs.length < cb.length) {//判断实参个数是否和原函数的形参个数的关系
return fn;
} else {
return cb(...arrs);
}
}
return fn;
}
// let sfn2 = curry2(sum);
// let twofn01 = sfn2(2);
// let twofn02 = twofn01(3);
// console.log(twofn01 == twofn02);//true
let sfn2 = curry2(sum);
let add23 = sfn2(2, 3);
console.log(add23(4, 5));//14
console.log(add23(5, 6));//14
七.反柯里化
// 反柯里化工具函数:
function uncurrying(fn) {
return function () {
return Function.prototype.call.apply(fn, arguments);
// 1、call函数(是apply的原函数)的this是fn;
//变成了:fn.call(arguments); //此处的arguments就是匿名函数的参数,此参数来自于下面调用push时传入的传参。
// 变成了:fn.call(push里的arguments,100);
// 最终表达的意思就是: push的arguments.fn(100);
}
};
const push = uncurrying(Array.prototype.push);
// let result = push()
function fn() {
// console.log("arguments",arguments);
push(arguments, 100);
console.log("arguments", arguments);
}
fn(12, 23, 34);
八.函数是个对象
function fn01() {
console.log("fn01");
}
let fn02 = function () {
console.log("fn02");
}
// 函数的定义:
// 其实,我们平时定义一个函数,背后就是通过 new Function() 来定义。
// 所以,函数就是个对象。
let fn03 = new Function(`console.log("fn03");`);
fn01();
fn02();
fn03();
console.dir(Function);