Why does for(var i in Math) not iterate through Math.* in Javascript?

前端 未结 4 720
旧巷少年郎
旧巷少年郎 2021-02-14 11:19

For some reason for(var i in Math){console.log(i)} doesn\'t show the expected tan, cos, atan2, E, PI in Javascript.

相关标签:
4条回答
  • 2021-02-14 11:46

    Those properties are non-enumerable.

    From the MDC documentation on for..in:

    A for...in loop does not iterate over built-in properties.

    In newer JavaScript implementations you can make your own non-enumerable properties. Check out propertyIsEnumerable() and Object.defineProperty().

    0 讨论(0)
  • 2021-02-14 11:54

    As with most built-in objects in JavaScript, properties and methods of the Math object are defined in the ECMAScript spec (section 15.8.1) as not being enumerable via the (inaccessible to script) DontEnum attribute. In ECMAScript 5, you can mark properties and methods of your own objects as being non-enumerable also:

    var o = {};
    
    Object.defineProperty(o, "p", {
        enumerable: false,
        value: 1
    });
    
    Object.defineProperty(o, "q", {
        enumerable: true,
        value: 2
    });
    
    for (var i in o) {
        console.log(i + "=>" + o[i]);
    }
    // q=>2
    
    0 讨论(0)
  • 2021-02-14 12:06

    I keep noticing when the actual method is not known people will tell you you shoud'nt do it

    The following is the way to expose private functions of a given object

    let exposeFunctionsOf  =(obj) =>
    {
        let iterated = false
        for ( let k in obj ) 
        {
            iterated = true;
            let prop = obj[k]
            if ( typeof props == "function")
            {
                window[k] = prop
            }
        }
        if (!iterated)
        {
           let props_names = Object.getOwnPropertyNames(obj);
           for (let prop_name of props_names)
           {
              iterated = true;
              let prop = obj[prop_name]
              if ( typeof prop == "function")
                window[prop_name] =prop
           }
        }
        if (!iterated)
        {
          console.warn("failed to iterate through the following object")
          cosnole.log(obj)
        }
    }
    

    Applied on Math object

    exposeFunctionsOf(Math)
    

    Now you can write sin(x) instead of Math.sin(x)

    Enjoy

    0 讨论(0)
  • 2021-02-14 12:06

    Because Math is a built in object whose properties are flagged non-enumerable. Many built in objects have this behavior, which is why looping over an array with for..in will not give you problems until Array.prototype is extended with user functions, which are always enumerable by default.

    Until recently non-enumerable was an internal property not accessible by regular Javascript code. However EMCAScript 5 specifies the ability to set the enumerability and writeability (try changing the value of Math.PI) of any object property through Object.defineProperty().

    It also provides Object.getOwnPropertyNames() as a way to get a list of all properties of an object regardless of their enumerability.

    Object.getOwnPropertyNames(Math);
    
    //returns
    ["LN10", "PI", "E", "LOG10E", "SQRT2", "LOG2E", "SQRT1_2", "LN2", "cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]
    

    Far as I know the only browsers that currently support these functions are Chrome and Safari. Firefox should support it at version 4. IE9 I am not sure about, but Microsoft has stated they intend to support the EMCAScript 5 standard eventually.

    I do not believe there is any way to emulate this functionality in Javascript interpreters without explicit support.

    0 讨论(0)
提交回复
热议问题