Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

为什么要有堆栈/关于[]==![]的计算规则 #4

Open
RachelRen opened this issue Jul 26, 2018 · 0 comments
Open

为什么要有堆栈/关于[]==![]的计算规则 #4

RachelRen opened this issue Jul 26, 2018 · 0 comments

Comments

@RachelRen
Copy link
Owner

RachelRen commented Jul 26, 2018

为什么要有堆栈

变量num,bol,str为基本数据类型,它们的值,直接存放在栈中,obj,person,arr为复合数据类型,他们的引用变量存储在栈中,指向于存储在堆中的实际对象。 由上图可知,我们无法直接操纵堆中的数据,也就是说我们无法直接操纵对象,但我们可以通过栈中对对象的引用来操作对象,就像我们通过遥控机操作电视机一样,区别在于这个电视机本身并没有控制按钮。

堆比栈大,栈比堆的运算速度快,对象是一个复杂的结构,并且可以自由扩展,如:数组可以无限扩充,对象可以自由添加属性。将他们放在堆中是为了不影响栈的效率。而是通过引用的方式查找到堆中的实际对象再进行操作。相对于简单数据类型而言,简单数据类型就比较稳定,并且它只占据很小的内存。不将简单数据类型放在堆是因为通过引用到堆中查找实际对象是要花费时间的,而这个综合成本远大于直接从栈中取得实际值的成本。所以简单数据类型的值直接存放在栈中。

简单数据类型比较稳定,占据比较小
对象类 占据比较大,可以扩充,为了不影响栈中的操作

##关于[]==![]的计算规则

逻辑非运算符的优先级高于 ==,

逻辑运算符的规则如下:

  1. 令expr为解释执行UnaryExpression的结果
  2. 令oldValue为ToBoolean(GetValue(expr))
  3. 如果oldValue为true, 返回false
  4. 返回true

所以在这段算法中,[]是object, ![]是boolean, 两者的类型不同, y是boolean类型,所以根据第八条,比较变成: [] == toNumber(Boolean)

上面的图中,可得出的结论是,如果x或者y有一个是number/string,那么都转换成ToNumber();
如果x或者y有一个是boolean,也都转换成ToNumber()

如果有一个是object,那么是object的ToPrimitive()来转换比较

==运算的规则

  1. undefined == null,结果是true。且它俩与所有其他值比较的结果都是false。

  2. String == Boolean,需要两个操作数同时转为Number。

  3. String/Boolean == Number,需要String/Boolean转为Number。

  4. Object == Primitive,需要Object转为Primitive(具体通过valueOf和toString方法)。

const toPrimitive = (obj, preferredType='Number') => {
    let Utils = {
        typeOf: function(obj) {
            return Object.prototype.toString.call(obj).slice(8, -1);
        },
        isPrimitive: function(obj) {
            let types = ['Null', 'String', 'Boolean', 'Undefined', 'Number'];
            return types.indexOf(this.typeOf(obj)) !== -1;
        }
    };
   
    if (Utils.isPrimitive(obj)) {
        return obj;
    }
    
    preferredType = (preferredType === 'String' || Utils.typeOf(obj) === 'Date') ?
     'String' : 'Number';

    if (preferredType === 'Number') {
        if (Utils.isPrimitive(obj.valueOf())) {
            return obj.valueOf()
        };
        if (Utils.isPrimitive(obj.toString())) {
            return obj.toString()
        };
    } else {
        if (Utils.isPrimitive(obj.toString())) {
            return obj.toString()
        };
        if (Utils.isPrimitive(obj.valueOf())) {
            return obj.valueOf()
        };
    }
}

剖析 JavaScript 各种蛋疼的类型转换

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant