说我有一个对象和一个函数定义:
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.....
如果函数定义是一个对象,为什么我不能枚举它的属性?有办法吗?
由于
答案 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
在严格模式下引用全局对象window
或undefined
。
用它作为构造函数:
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
循环将是一个重大改变。