EdwardZZZ / articles

工作点滴记录
2 stars 0 forks source link

mixin get set #66

Open EdwardZZZ opened 4 years ago

EdwardZZZ commented 4 years ago
import typeHelper from './typeHelper';

/**
 * 混入目标,暂不考虑 引用 & Map & Set
 * @param target 目标
 * @param source 资源
 */
export default function mixin(deep: boolean = false, target: any, ...sources: any[]) {
    if (!typeHelper.isObject(target)) return target;

    for (const source of sources) {
        if (!typeHelper.isObject(source)) continue;

        const keys = Reflect.ownKeys(source);

        for (const key of keys) {
            const descriptor = Reflect.getOwnPropertyDescriptor(source, key);
            const { get, set, value } = descriptor;

            if (get || set) {
                // const desc: PropertyDescriptor = { configurable: true };

                // if (get) desc.get = get;
                // if (set) desc.set = set;

                Reflect.defineProperty(target, key,  descriptor);
            } else if (Reflect.has(descriptor, 'value')) {
                Reflect.set(target, key, deep && typeHelper.isObject(value) ? mixin(true, Reflect.get(target, key) || {}, value) : value);
            }
        }
    }

    return target;
}
EdwardZZZ commented 3 years ago
const Type = (obj) => Object.prototype.toString.call(obj).slice(8, -1);
const complexType = (type) => ['Array', 'Object'].includes(type);

const CloneDeep = (value) => {
    if (!complexType(Type(value))) return value;

    const result = Array.isArray(value) ? [] : {};
    // const task = [[value, result]]; // [source, dest][]
    const task = [value, result];
    const ref = new Set();

    while (task.length) {
        // const [source, dest] = task.shift();
        const [source, dest] = task.splice(0, 2);

        for (const k in source) {
            if (!source.hasOwnProperty(k)) continue;

            const desc = Reflect.getOwnPropertyDescriptor(source, k);
            const { value: v, get, set } = desc;

            if (get || set || !complexType(Type(v))) {
                Reflect.defineProperty(dest, k, desc);
            } else {
                if (ref.has(v)) {
                    dest[k] = v;
                } else {
                    dest[k] = Array.isArray(v) ? [] : {};
                    task.push(v, dest[k]);
                }
            }
        }

        ref.add(source);
    }

    return result;
};