zhaobinglong / myBlog

https://zhaobinglong.github.io/myBlog/
MIT License
7 stars 0 forks source link

js数据类型之Object #21

Open zhaobinglong opened 4 years ago

zhaobinglong commented 4 years ago

js中,万物皆对象。flutter中万物皆widget,语言都有相通的地方

三种方式

var person = {name:'zb',gender: '1'}    // 方法一:对象字面量的方式
var person = new Object();              // 方法二:Object是系统的构造函数,new的方式
function P(){};                                   // 方法三:定义构造函数创建对象,按约定首字母大写,后面原型继承都用它
var person = new P();  

Object.create(null)

直接创建一个干净的对象,没有继承关系, 好处是不用考虑会和原型链上的属性重名问题, 但是原型上的方法你都不能用了

合并对象

// 合并两个对象,返回一个新对象,
// 如果两个对象有相同的属性,后者的值将会覆盖前者的值
// 如果属性还是对象,则就是引用,修改的话会影响两个对象
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign({}, source, source);
const returnedTarget = {...target, ...source}

遍历对象

// 方法一:
for (let key in obj) {
  // console.log(obj[key])
}

拷贝对象

const newTarget = Object.assign({}, oldTarget);
zhaobinglong commented 4 years ago

Object.prototype.toString.call判断数据类型

toString()是它原型链上的方法

zhaobinglong commented 4 years ago

奇妙的属性之valueOf

var a = {}
a.valueOf = function(){ return "hello world!" }
a == "hello world!" // true
a === "hello world!" // false,严格等于操作符会比较数据类型
zhaobinglong commented 4 years ago

判断对象是否相等

方法一:通过JSON.stringify(obj)来判断两个对象转后的字符串是否相等

优点:用法简单,对于顺序相同的两个对象可以快速进行比较得到结果 缺点:这种方法有限制就是当两个对比的对象中key的顺序不是完全相同时会比较出错

方法二:循环判断

// 对Object扩展一个方法chargeObjectEqual
Object.prototype.chargeObjectEqual = function(obj){
    // 当前Object对象
    var propsCurr = Object.getOwnPropertyNames(this);
    // 要比较的另外一个Object对象
    var propsCompare = Object.getOwnPropertyNames(obj);
    if (propsCurr.length != propsCompare.length) {
        return false;
    }
    for (var i = 0,max = propsCurr.length; i < max; i++) {
        var propName = propsCurr[i];
        if (this[propName] !== obj[propName]) {
            return false;
        }
    }
    return true;
}

方法三:循环+递归判断


    function deepCompare(x, y) {
        var i, l, leftChain, rightChain;

        function compare2Objects(x, y) {
            var p;

            // remember that NaN === NaN returns false
            // and isNaN(undefined) returns true
            if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
                return true;
            }

            // Compare primitives and functions.     
            // Check if both arguments link to the same object.
            // Especially useful on the step where we compare prototypes
            if (x === y) {
                return true;
            }

            // Works in case when functions are created in constructor.
            // Comparing dates is a common scenario. Another built-ins?
            // We can even handle functions passed across iframes
            if ((typeof x === 'function' && typeof y === 'function') ||
                (x instanceof Date && y instanceof Date) ||
                (x instanceof RegExp && y instanceof RegExp) ||
                (x instanceof String && y instanceof String) ||
                (x instanceof Number && y instanceof Number)) {
                return x.toString() === y.toString();
            }

            // At last checking prototypes as good as we can
            if (!(x instanceof Object && y instanceof Object)) {
                return false;
            }

            if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
                return false;
            }

            if (x.constructor !== y.constructor) {
                return false;
            }

            if (x.prototype !== y.prototype) {
                return false;
            }

            // Check for infinitive linking loops
            if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
                return false;
            }

            // Quick checking of one object being a subset of another.
            // todo: cache the structure of arguments[0] for performance
            for (p in y) {
                if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
                    return false;
                } else if (typeof y[p] !== typeof x[p]) {
                    return false;
                }
            }

            for (p in x) {
                if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
                    return false;
                } else if (typeof y[p] !== typeof x[p]) {
                    return false;
                }

                switch (typeof(x[p])) {
                    case 'object':
                    case 'function':

                        leftChain.push(x);
                        rightChain.push(y);

                        if (!compare2Objects(x[p], y[p])) {
                            return false;
                        }

                        leftChain.pop();
                        rightChain.pop();
                        break;

                    default:
                        if (x[p] !== y[p]) {
                            return false;
                        }
                        break;
                }
            }

            return true;
        }

        if (arguments.length < 1) {
            return true; //Die silently? Don't know how to handle such case, please help...
            // throw "Need two or more arguments to compare";
        }

        for (i = 1, l = arguments.length; i < l; i++) {

            leftChain = []; //Todo: this can be cached
            rightChain = [];

            if (!compare2Objects(arguments[0], arguments[i])) {
                return false;
            }
        }

        return true;
    }

参考

https://www.jianshu.com/p/90ed8b728975