函数定义是一个对象吗?

时间:2017-07-09 09:38:54

标签: javascript

说我有一个对象和一个函数定义:

var jane = {
    firstName: 'Jane',
    lastName: 'Smith',
    describe: function () {
        return 'Person named '+this.firstName+this.lastName
    },
};

function Car (desc) {
    this.desc = desc;
    this.color = "red";
    this.getInfo = function getInfo() {
        return 'A ' + this.color + ' ' + this.desc + '.';
    };
}

我可以枚举对象的键:值对,因此:

obj=jane
for (var prop in obj) {
  console.log(`obj.${prop} = ${obj[prop]}`);
}

但是函数定义失败(函数表达式相同)

obj=Car.....

如果函数定义是一个对象,为什么我不能枚举它的属性?有办法吗?

由于

4 个答案:

答案 0 :(得分:2)

让我们想象你站在汽车工厂前面。你能预测下一辆车会离开吗?或许工厂关闭,什么都不返回?

import Car from "factory";
var car=new Car();//what will car be?

所以基本上你无法预测构造函数将构造什么。但如果汽车厂只生产柴油发动机,我们可以通过原型链找到它,例如:

new Car() instanceof Diesel;//true
new Car instanceof Car;//true => all cars have the same prototype ( Car.prototype)

回到你的例子,如果属性是静态的,那么使用像这样的继承是有意义的:

function Car (desc) {
this.desc = desc;//unpredictable
}
Car.prototype={
  color:"red",//predictable, every car inherits from this
  getInfo() {
    return 'A ' + this.color + ' ' + this.desc + '.';
  },
};

因此,为了获得静态属性,您可以遍历原型:

for(key in Car.prototype);//iterates over color and getInfo

答案 1 :(得分:0)

在这种情况下,this在严格模式下引用全局对象windowundefined。 用它作为构造函数: obj = new Car(desc)

答案 2 :(得分:0)

当函数是对象时,函数内的this特殊对象的属性在函数本身的for...in循环中不是enumerable ...

如果你不喜欢new this this {{}}} {{}} {{}} {{}} {{}} {{{}} {{{{{{{{{{{{{{{{{使用明确的var obj = {}; Car.call(obj); 参数来bind,如下所示:

function Car(desc) {
  this.desc = desc;
  this.color = "red";
  this.getInfo = function getInfo() {
    return 'A ' + this.color + ' ' + this.desc + '.';
  };
}

var obj = {};
Car.call(obj);

for (var prop in obj) {
  console.log(`obj.${prop} = ${obj[prop]}`);
}



function simpleThisInspector(constructorFn) {
  const source = constructorFn.toString()
  const thisProps = {}
  // TODO: nested {} blocks and non-block multiline statements not supported
  const re = /this\.(\w+)\s*=\s*([^;\n{]*(?:\{[^}]*})?)/g  // https://regex101.com/r/aJzgjx/1
  let match
  while(match = re.exec(source)) {
    thisProps[match[1]] = match[2]
  }
  return thisProps
}

var obj = simpleThisInspector(Car)




一个更复杂的路线从解析函数源代码开始:call

function simpleThisInspector(constructorFn) {
  const source = constructorFn.toString()
  const thisProps = {}
  // TODO: nested {} blocks and non-block multiline statements not supported
  const re = /this\.(\w+)\s*=\s*([^;\n{]*(?:\{[^}]*})?)/g  // https://regex101.com/r/aJzgjx/1
  let match
  while(match = re.exec(source)) {
    thisProps[match[1]] = match[2]
  }
  return thisProps
}

function Car(desc) {
  this.desc = desc;
  this.color = "red";
  this.getInfo = function getInfo() {
    return 'A ' + this.color + ' ' + this.desc + '.';
  };
}

var obj = simpleThisInspector(Car)

for (var prop in obj) {
  console.log(`obj.${prop} = ${obj[prop]}`);
}



java.lang.IllegalStateException: 
  at android.support.v4.view.ViewPager.populate(ViewPager.java:1167)
  at android.support.v4.view.ViewPager.populate(ViewPager.java:1116)
  at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1642)
  at android.view.View.measure(View.java:17951)
  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5797)
  at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
  at android.view.View.measure(View.java:17951)
  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5797)
  at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
  at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
  at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
  at android.view.View.measure(View.java:17951)
  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5797)
  at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
  at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2910)
  at android.view.View.measure(View.java:17951)
  at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2048)
  at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1185)
  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1406)
  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1073)
  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5988)
  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
  at android.view.Choreographer.doCallbacks(Choreographer.java:580)
  at android.view.Choreographer.doFrame(Choreographer.java:550)
  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
  at android.os.Handler.handleCallback(Handler.java:739)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:135)
  at android.app.ActivityThread.main(ActivityThread.java:5910)
  at java.lang.reflect.Method.invoke(Native Method:0)
  at java.lang.reflect.Method.invoke(Method.java:372)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)




答案 3 :(得分:0)

你是正确的,函数定义是一个对象,但你想要实现的是迭代在该函数的内部之类的东西,这是不可能的(想象试图迭代一个函数的局部变量 - 看起来很傻,你有一种类似的概念)。你可以随时尝试

obj = new Car("dummy");

将迭代函数返回的对象。如果不调用new,就无法从外部访问这些属性。

请注意,这些属性不是在函数对象上定义的属性。它们是该函数返回的对象的属性。所以JavaScript需要一些新的语法,因为使用简单的for .. in循环将是一个重大改变。