- 如何检测到对象中有循环引用
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 被当作空格
*/
class A {}; class B extends A{},问:new B() instanceof B,new B() instanceof A的结果
new B() instanceof B // true
new B() instanceof A // true
- 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();
- _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}}
- _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);
}
- _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);
}
}