jslib-book / jslib-book-code

9 stars 0 forks source link

199 页的中间件串联 #16

Open cinyearchan opened 1 year ago

cinyearchan commented 1 year ago
isEqual(a1, a2, (next) => functionMiddleware(nanMiddleware())(next))  // 这里得到的还是 false
fengyangfifa commented 1 year ago

这是我按照作者的实现改良了一下

function type(data) {
  return Object.prototype.toString.call(data).slice(8, -1).toLowerCase()
}

function equalArray(value, other, enhancer) {
  if (value.length !== other.length) {
    return false;
  }

  for (let i = 0; i < value.length; i++) {
    if (!isEqual(value[i], other[i], enhancer)) {
      return false;
    }
  }

  return true;
}

function equalObject(value, other, enhancer) {
  const vKeys = Object.keys(value);
  const oKeys = Object.keys(other);

  if (vKeys.length !== oKeys.length) {
    return false;
  }

  for (let i = 0; i < vKeys.length; i++) {
    const v = value[vKeys[i]];
    const o = other[vKeys[i]];

    if (!isEqual(v, o, enhancer)) {
      return false;
    }
  }

  return true;
}

function isEqual(value, other, enhancer) {
  if (value === other) {
    return true;
  }

  const vType = type(value);
  const oType = type(other);

  if (vType !== oType) {
    return false;
  }

  if (vType === 'array') {
    return equalArray(value, other, enhancer);
  } else if (vType === 'object') {
    return equalObject(value, other, enhancer);
  }

  const next = () => {
    return value === other;
  }

  if (type(enhancer) === 'function') {
    return enhancer(next)(value, other);
  }

  return next();
}

function nanMiddleware() {
  return (next) => (value, other) => {
    if (Number.isNaN(value) && Number.isNaN(other)) {
      return true;
    }

    return next(value, other);
  }
}

function functionMiddleware() {
  return (next) => (value, other) => {
    if (type(value) === 'function' && type(other) === 'function') {
      return value.toString() === other.toString();
    }

    return next(value, other);
  }
}

function compose(...fns) {
  return fns.reduce((a, b) => (...args) => a(b(...args)));
}

const test3 = () => {
}
const test4 = () => {
}

const a1 = {a: NaN, b: test3};
const a2 = {a: NaN, b: test4};
console.log(isEqual(1, NaN, nanMiddleware()));
console.log(isEqual(a1, a2, compose(functionMiddleware(), nanMiddleware())));
console.log(isEqual(a1, a2, compose(nanMiddleware(), functionMiddleware())));
console.log(isEqual(a1, a2, (next) => functionMiddleware(nanMiddleware(next))));
console.log(isEqual([NaN], [NaN], nanMiddleware()));
yanhaijing commented 1 year ago

感谢反馈

yanhaijing commented 1 year ago

https://github.com/jsmini/isequal 这里有一个实战版的代码,可以看看

daolanfler commented 1 year ago

主要在于非 compose 写法里面: next 应该作为「 nanMiddleware() 返回值」的参数吧。

// 感觉这个 next 也放错地方了 
console.log(isEqual(a1, a2, (next) => functionMiddleware(nanMiddleware(next)))); // true

// 我感觉应该是这样的,从上面 compose 的角度来说:
console.log(  isEqual(a1, a2, (next) => functionMiddleware(nanMiddleware()(next)))     ); // true 
//                                                                         ^?

// 书中是这样的
console.log(  isEqual(a1, a2, (next) => functionMiddleware(nanMiddleware())(next))   );  // false 
//                                                                          ^?

借用2楼的代码 @fengyangfifa ,在线 stackblitz link