【问题标题】:Why functions are objects in javascript?为什么函数是javascript中的对象?
【发布时间】:2015-02-15 17:08:52
【问题描述】:

请解释一下为什么函数是javascript中的对象? 对象是具有属性的结构。属性的值可能是一个函数,我们称这个属性为方法。 但是我们不能执行一个对象。 我们不能这样做:

var cat = {name: 'Murzik', age: 17};
cat();

但是我们可以执行函数

var func = function() {
    alert('Hello world!');
};
func();

那么,如果函数是对象,为什么我们可以这样做呢? 请帮我理解! 谢谢!

【问题讨论】:

  • Javascript 的设计者只是简单地决定一个函数将从一个对象派生,因此它本身可以具有属性。您还在寻找什么其他类型的答案?数组也是从对象派生的。函数是派生对象,因此具有常规对象的所有功能以及派生实现中添加的一些附加功能。这就是继承的工作原理。
  • 如果您真的对 javascript 很认真,并且了解它与其他语言的区别,我会选择 Douglas Crockford 的 JavaScript: The Good Parts 的副本。如果您认为函数在 javascript 中具有时髦的味道,那么您会喜欢truthy/falsey、闭包和 javascript 数学之类的东西。 0.1 + 0.2 == 0.3 是假的。
  • 函数是对象,但对象不是函数。这是什么意思? is a 不等价。
  • @Lawrence - 浮点数学等价怪癖并不是 JavaScript 独有的。
  • 不是独一无二的,但在地雷中:)

标签: javascript function object


【解决方案1】:

因为 ECMAScript 规范是这样说的:

4.3.24 function

作为标准内置实例的 Object 类型的成员 Function 构造函数,可以作为子例程调用

注意

  • 有些对象是不可调用的:

    var obj = {};
    typeof obj; // "object" --> It's not callable
    obj(); // TypeError: obj is not a function
    
  • 有些对象是可调用的,但不是函数:

    var obj = document.createElement('object');
    typeof obj; // "function" --> It's callable
    obj instanceof Function; // false --> It's not a function
    
  • 有些对象是可调用的并且是函数:

    function obj(){}
    typeof obj; // "function" --> It's callable
    obj instanceof Function; // true --> It's a Function instance
    
  • 并非所有Function 实例都是可调用的:

    var obj = Object.create(Function.prototype);
    obj instanceof Function; // true --> It's a Function instance
    typeof obj; // "object" --> It's not callable
    obj(); // TypeError: obj is not a function
    

【讨论】:

    【解决方案2】:

    这就是语言的设计方式。函数是引用类型(它们作为指针传递),JavaScript 引用类型可能有子引用。我认为您正在努力协调来自 C++ 或 Java 的对象模型(具有特权方法的结构)与另一种语言提供的类型糖。

    我不确定 Brendan Eich 在什么时候选择将函数实现为对象的实例,但我怀疑原因是它与使函数成为一等变量是一致的。对象已经作为一种变量存在,使用现有变量类型对函数进行建模可能是有意义的。你得直接问他。

    一个方便的副作用是它允许我们在函数上存储元数据。这在执行缓存或执行任何其他需要在函数调用之间保持状态的事情时会很方便:

    function myCachedFunction(argument) {
        myCachedFunction.cache = myCachedFunction.cache || {};
        myCachedFunction.cache[argument] = myCachedFunction.cache[argument] || operation();
    
        return myCachedFunction.cache[argument];
    
        function operation() {
            // performs action with argument
            // only gets called if no cache lookup for argument
        }
    }
    

    有些函数还需要知道它们何时被调用。这可以通过闭包变量来实现,但函数字段有时可能是更优雅的解决方案:

    function getUniqueID() {
        getUniqueID._calls = getUniqueID._calls || 0;
        return getUniqueID._calls++;
    }
    

    【讨论】:

    • 当函数是原始值时,拥有applytoString 甚至不需要任何特殊情况。方法也适用于其他原始类型
    • @Bergi - 是的,这是真的。我想那不可能是设计背后的原因。尽管我注意到原语方法的方式非常不连贯——您可以在字符串上分配字段,但分配陷入了黑洞。您可能会争辩说不一致之处在于原语而不是功能;我想知道 Eich 和 co 是否只是觉得,例如。扩展字符串“太奇怪了”,因此打破了他们自己的模型以保持“直观”。
    【解决方案3】:

    仅仅是因为它们是……这就是语言的设计者决定做的事情。

    【讨论】:

      【解决方案4】:

      如果一个对象是可调用的,你会期望发生什么?您可以将对象视为存储,将函数视为您可以执行的东西。此外,函数不是对象,而是它们的超集。因此,像 jquery 这样的库是可能的,原型继承也是可能的,这就是您在 JavaScript 中创建类的方式。

      function Car() {
          this.tires = 4;
      }
      
      Car.prototype.hi = function() {
          console.log("hi");
      }
      
      var myCar = new Car();
      
      console.log(myCar.tires); // 4
      myCar.hi(); // hi
      

      还有静态方法

      Car.bye = function() {
          console.log("bye");
      }
      
      Car.bye(); // bye
      myCar.bye(); // this is an error
      

      【讨论】:

      • 我不知道如何用英语解释它... :( 我不明白函数是什么样子的?如果我们在对象中有一个方法,我们可以调用它,当然。var obj = { method: function() { alert(1) } }; obj.method();但是我们怎么调用函数呢?我们调用的是什么方法,什么时候调用函数,如果我们认为一个对象是一个有属性的存储。
      • @Kotik - 没有方法调用。函数只是一种引用类型,具有取消引用过程的额外能力。
      • @Kotik:我们称之为你看不到的内部“调用”方法。
      猜你喜欢
      • 2010-09-27
      • 2011-03-15
      • 2017-10-13
      • 2016-05-13
      • 1970-01-01
      • 2014-02-16
      • 2012-12-19
      • 2020-07-30
      • 1970-01-01
      相关资源
      最近更新 更多