每日一题

100 阅读1分钟
  1. 如何检测到对象中有循环引用
const A = {a: '1',b: '2',c: A}

循环引用对象序列化时会报错

try {
    JSON.stringify(A)
 } catch(e){
     console.log(e)
 }
    

延伸知识:JSON.stringify() 用来把对象或者值转化为json字符串,当在循环引用时会抛出异常TypeError ("cyclic object value")(循环对象值)

interface stringifyType {
    value: any;
    replacer?: (key: any, v: any) => string | string[];
    space: number < 10|number < 1 | string;
}
/** space 参数说明
* give a 1 < number < 10 when return then 输出对应的空格
* give a number < 1 when return then 输出没有空格
* give a string when return then the string 被当作空格
*/
  1. class A {}; class B extends A{},问:new B() instanceof B, new B() instanceof A 的结果
new B() instanceof B // true

new B() instanceof A // true
  1. ES6 extends语法糖其实是什么继承方式 答曰组合继承,例如:
class C {

}
class D extends C {
  print() {
    console.log('this is D')
  }
}

export const instance2 = new D()
instance2.print()

为了直观的看输出,不妨初始化一个rollup项目,不想看可以直接跳过看输出

yarn init -y

yarn add rollup rollup-plugin-babel @babel/core @babel/preset-env -D

// package.json

{
    "scripts": { "dev": "rollup -c -w"}
}
// 配置rollup.config.js

import babel from 'rollup-plugin-babel'

export defalut {
    input: 'src/index.js',
    output: {
        file: 'build/bundle.js',
        format: 'cjs'
    },
    plugins: [babel({ exclude: 'node_modules/**'})]
    
}
// .babelrc
{
    presets: ['preset-env']
}

输出

var C = /*#__PURE__*/_createClass(function C() {  // 1 _createClass() 创建一个类
  _classCallCheck(this, C);  
});
var D = /*#__PURE__*/function (_C) {
  _inherits(D, _C);  //2
  var _super = _createSuper(D); // 4
  function D() {
    _classCallCheck(this, D);
    return _super.apply(this, arguments);
  }
  _createClass(D, [{  
    key: "print",
    value: function print() {
      console.log('this is D');
    }
  }]);
  return D;
}(C);

var instance2 = new D();

instance2.print();
  1. _createClass()
// Constructor: function C() 和 function D()
function _createClass(Constructor, protoProps, staticProps) {
    // Constructor.prototype === Object
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", {
  // 当 `writable` 属性设置为 `false` 时,该属性被称为“不可写的”。它不能被重新赋值。
    writable: false
  });
  return Constructor;
}

由此可知创建C类的时候 _createClass 的第二个参数和第三个参数为空,只会执行Object.defineProperty()

Object.defineProperty方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。 备注: 应当直接在 Object 构造器对象上调用此方法,而不是在任意一个 Object 类型的实例上调用。

到这里执行完返回的是个

f C(){name: "C",length: 0,prototype: {[[Prototype]]: Object}}
  1. _inherits(D, C)
function _inherits(subClass, superClass) {
   // 先判断父类是否存在
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  // 原型链和构造函数继承 用父类的显示原型创建一个__proto__ 连接的新对象 可以用 
  // subClass.prototype.__proto__ === superClass.prototype
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      writable: true,
      configurable: true
    }
  });
  Object.defineProperty(subClass, "prototype", {
    writable: false
  });
  if (superClass) _setPrototypeOf(subClass, superClass);
}
  1. _classCallCheck
function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

function _defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false;
    descriptor.configurable = true;
    if ("value" in descriptor) descriptor.writable = true;
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}