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

Bug about _.keys()? #2799

Closed
rookieLink opened this issue Feb 1, 2019 · 2 comments
Closed

Bug about _.keys()? #2799

rookieLink opened this issue Feb 1, 2019 · 2 comments

Comments

@rookieLink
Copy link

I read underscore's code about _.keys()
if I want to invoke the code in IE7, there will be:
`
function A (){}
A.prototype.toString = 'test';

var a = new A();
a.toString = 'test';
_.keys(a); //there should be [] rather than ['toString']?
`
right? I need some help

@HelloAny
Copy link

 _.keys = function(obj) {
    if (!_.isObject(obj)) return [];
    if (nativeKeys) return nativeKeys(obj);
    var keys = [];
    for (var key in obj) if (has(obj, key)) keys.push(key);
    // Ahem, IE < 9.
    if (hasEnumBug) collectNonEnumProps(obj, keys);
    return keys;
  };
_.isObject = function(obj) {
   var type = typeof obj;
   return type === 'function' || type === 'object' && !!obj;
 };

Here you can verify the function

@jgonggrijp
Copy link
Collaborator

@rookieLink If you do just this,

function A (){}
A.prototype.toString = 'original value';

var a = new A();

Then a.toString is only an inherited property of a and _.keys(a) will be []. The internal structure of a looks like this ([[Prototype]] is an abstract property of each object that you cannot access directly):

{
    [[Prototype]]: {
        constructor: A,
        toString: 'original value'
    }
}

If you now also do this:

a.toString = 'new value';

Then you create an extra own property on a that shadows the toString property of the prototype:

{
    toString: 'new value',
    [[Prototype]]: {
        constructor: A,
        toString: 'original value'
    }
}

So it is important to understand that when you do

A.prototype.toString = 'original value';

this just sets a “default value” for the toString property of instances of A in case they don’t have an own property with that name.

Hope this answers your question. I will close this issue now, but feel free to comment again.

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

3 participants