Javascript中数学和数组的区别是什么?

Javascript中数学和数组的区别是什么?,javascript,arrays,Javascript,Arrays,Javascript在其内置类型和对象方面似乎有一些自由 要获取数组类型中的函数,可以执行以下操作: > Array().slice function slice() { [native code] } 所以这里的数组看起来像一个标准函数,被用作构造函数。除了slice不是Array()函数的成员函数,它是Array对象的成员函数 Array()的另一个不寻常之处是,无论是否使用new()调用它,它似乎都会返回一个数组对象: 另一方面,Math似乎是一个始终存在的内置单

Javascript在其内置类型和对象方面似乎有一些自由

要获取数组类型中的函数,可以执行以下操作:

> Array().slice
  function slice() {
     [native code]
  }
所以这里的数组看起来像一个标准函数,被用作构造函数。除了slice不是Array()函数的成员函数,它是Array对象的成员函数

Array()的另一个不寻常之处是,无论是否使用new()调用它,它似乎都会返回一个数组对象:

另一方面,Math似乎是一个始终存在的内置单例对象(即:无需实例化)。因此,您可以使用Math.min.apply,而使用Array().slice.apply处理数组

我的问题是,是什么让Array()与您自己编写的构造函数和Javascript的其他内置对象如此不同。

您正在编写的

 Array().slice()
这意味着:

  • 调用“Array”函数
  • 在返回值上查找名为“slice”的属性
  • 将该属性的值视为对函数的引用,并调用它
  • “slice”函数是在数组原型对象上定义的,这意味着数组的每个实例都可以通过该属性名访问它。这里的关键是,您所称的“数组函数”由符号“Array”引用。当您编写“Array()”时,这意味着调用函数,因此该表达式引用数组实例。构造函数和常规函数之间并没有太大区别;实际上,正是
    new
    关键字通过改变调用函数的方式(即,使用新创建的对象实例作为
    上下文值)起到了作用。函数可以自由地检查
    是否引用了全局对象,如果是,则可以主动返回新创建的对象

    “数学”对象只是一个对象;您可以将其定义如下:

    var Math = {
      min: function(n1, n2) { ... },
      max: function(n1, n2) { ... },
      // ...
    };
    

    我将引用你的问题,在线发表一些评论:

    除了。。。slice不是Array()函数的成员函数,它是Array对象的成员函数

    更确切地说,
    slice
    Array.prototype
    对象的成员,通过执行
    Array()
    ,您正在创建一个新的数组对象,该对象继承自
    Array.prototype
    ,这就是
    slice
    可用的原因

    Array()的另一个不寻常之处是,无论是否使用new()调用它,它似乎都会返回一个数组对象:

    此行为也由其他内置构造函数共享,例如
    函数

    var fn = Function('return "foo";');
    
    相当于:

    var fn = new Function('return "foo";');
    
    规范(vs)中对这些情况进行了描述,但当您在使用或不使用
    new
    时,其他构造函数会呈现不同的行为,例如,基本包装器:

    new Number("20");        // produces a Number object
    typeof new Number("20"); // "object"
    
    Number("20");            // makes type conversion
    typeof Number("20");     // "number"
    
    另一方面,Math似乎是一个始终存在的内置单例对象(即:无需实例化)。因此,您可以使用Math.min.apply,而使用Array().slice.apply处理数组

    是的,
    Math
    是一个简单的对象,而不是像
    Array
    那样的函数

    它继承自
    对象。prototype
    和IIRC它与简单用户定义对象的唯一独特区别是它的内部
    [[Class]]]
    属性包含“Math”,例如:

    我的问题是,是什么让Array()与您自己编写的构造函数和Javascript的其他内置对象如此不同

    Array
    没有什么不同,如果使用
    new
    调用或不调用,您可以编写一个行为与之相同的构造函数,例如:

    function Foo (arg) {
      if (!(this instanceof Foo)) { return new Foo(arg); }
      this.foo = arg;
    }
    
    new Foo('bar'); // { foo: 'bar' }
    Foo('bar');     // { foo: 'bar' }
    

    至少在Chrome中,数学就是一个例子。在Firefox上,它直接包装到本机代码,甚至在
    for in
    循环中都不可用。是的,我确信它并没有真正定义成这样-我的意思是,这只是对象性质的一个说明。@Ivo,无法使用
    for in
    循环枚举
    Math
    对象的属性,因为它们被描述为不可枚举,例如:
    Math.propertyEnumerable('max')生成
    @CMS Ah ok。但Opera很奇怪,你可以调用Math的构造函数,却得到了一个没有原型的无用对象,因此没有函数。@必须报告Ivo,这是一件非常糟糕的事情,它完全反对:“Math的
    对象没有
    [[Construct]]
    属性;无法将
    Math
    对象用作带有
    new
    运算符的构造函数。此外:“
    Math
    对象没有
    [[Call]]
    属性;无法将
    Math
    对象作为函数调用。”
    Object.prototype.toString.call(Math); // "[object Math]"
    
    function Foo (arg) {
      if (!(this instanceof Foo)) { return new Foo(arg); }
      this.foo = arg;
    }
    
    new Foo('bar'); // { foo: 'bar' }
    Foo('bar');     // { foo: 'bar' }