我正在玩NodeJS,我注意到了一些奇怪的东西。
我只是通过下面的代码探索构造函数的使用。
// We declare the constructor.
function Personne(inName) {
console.log("go!");
if ('undefined' != typeof inName) {
this.name = inName;
}
}
// We declare the object's prototype (that will be used by the constructor).
var PersonnePrototype = {
name: 'toto',
setName: function(inName) {
this.name = inName; // "this" refers to the new object being created.
},
getName: function() {
return this.name; // "this" refers to the new object being created.
}
};
Personne.prototype = PersonnePrototype;
var p = new Personne("Tom");
console.log("p.getName(): " + p.getName());
console.log(p);
console.log(Object.getPrototypeOf(p));
首先,我希望构造函数Personne(inName)
中的代码在使用运算符 new
时执行。
显然,情况并非如此。下面,我给出执行的输出。
$ node loop-closure.js
p.getName(): toto
{ prototype: { name: false, setName: [Function], getName: [Function] } }
{ name: 'toto', setName: [Function], getName: [Function] }
您可以看到构造函数未执行...
但是,如果我在 Chrome 或 Firefox 上执行相同的代码,则执行构造函数!
火狐:
"go!"
"Given: Tom"
"p.getName(): Tom"
Object { name: "Tom" }
Object { name: "toto", setName: window.onload/PersonnePrototype.setName(inName), getName: window.onload/PersonnePrototype.getName() }
铬:
go!
Given: Tom
p.getName(): Tom
Personne {name: "Tom", setName: function, getName: function}
Object {name: "toto", setName: function, getName: function}
我认为 NodeJS 是 Chrome 使用的 JavaScript 解释器。如果这是正确的,那么为什么Chrome和NodeJS之间的解释不同?
更新
我看到了评论,我尝试这样做:
我只是将代码复制/粘贴到一个文件中,然后在该文件上调用 NodeJs。
是的,你是对的:它按预期工作。
然后我找到了导致问题的原因。
我在执行的文件中有额外的代码。我在我给你的代码段之后放了一个 return 语句。下面,我给你完整的代码:
我正在使用 NodeJs 版本 0.10.35:
$ node -v
v0.10.35
// We declare the constructor.
function Personne(inName) {
console.log("go!");
if ('undefined' != typeof inName) {
this.name = inName;
}
}
// We declare the object's prototype (that will be used by the constructor).
var PersonnePrototype = {
name: 'toto',
setName: function(inName) {
this.name = inName; // "this" refers to the new object being created.
},
getName: function() {
return this.name; // "this" refers to the new object being created.
}
};
Personne.prototype = PersonnePrototype;
var p = new Personne("Tom");
console.log("p.getName(): " + p.getName());
console.log(p);
console.log(Object.getPrototypeOf(p));
return;
console.log("Does the prototype has a constructor property ? " + Object.getPrototypeOf(p).hasOwnProperty('constructor'));
// Other way to say the same thing:
function Personne() {
this.prototype = {
name: false,
setName: function(inName) {
this.name = inName; // "this" refers to the new object being created.
},
getName: function() {
return this.name; // "this" refers to the new object being created.
}
}
};
var p = new Personne(); // Object "p" has a parent. This parent has been created by the prototype (which is a function).
p.setName("Tom");
console.log("The name is " + p.getName() + " / " + this.name);
console.log("Does the prototype has a constructor property ? " + Object.getPrototypeOf(p).hasOwnProperty('constructor'));
// Ou encore :
var p = Object.create(Personne.prototype);
p.setName("Tom");
console.log("The name is " + p.getName() + " / " + this.name);
// We can see the difference between the prototype and the instanced object.
// Both are objects.
// However, as you can see, they do not present the same properties.
utils.dump(Object.getPrototypeOf(p));
Object.getPrototypeOf(p).name;
utils.dump(p);
if (Object.getPrototypeOf(p).getName() != p.getName()) {
console.log("The prototype and the object have different properties.");
console.log("Prototype: " + Object.getPrototypeOf(p).getName());
console.log("Object: " + p.getName());
}
// ------------------------------------------------------------------------------------
// Heritage
// ------------------------------------------------------------------------------------
function Personne() {
this.prototype = {
name: false,
setName: function(inName) {
this.name = inName; // "this" refers to the new object being created.
},
getName: function() {
return this.name; // "this" refers to the new object being created.
}
}
};
function student() {
Personne.call(this);
}
我虽然返回语句后的代码没有干扰。显然,确实如此。
NodeJs 在执行之前编译所有代码。因此,如果我稍后在代码中重新定义构造函数,那么它将修改它的第一个匹配项。
好的,但是:
var v = 1;
console.log("v = " + v);
var v = 2;
console.log("v = " + v);
输出:
$ node test1.js
v = 1
v = 2
和:
var v = 1;
console.log("v = " + v);
return;
var v = 2;
console.log("v = " + v);
输出:
$ node test1.js
v = 1
并且(可能有参考资料):
var v = { a: 1 };
console.log("v.a = " + v.a);
return;
var v = { a: 2 };
console.log("v.a = " + v.a);
输出:
$ node test1.js
v.a = 1
这里没有什么不寻常的...return 语句后面的代码似乎不会更改 return 语句之前的代码。
@Alexey十
感谢您的提示。
测试1.js:
function Construct() { this.name = "Tom"; }
var v = new Construct();
console.log("v.name = " + v.name);
return;
function Construct() { this.name = "Joe"; }
测试2.js:
var Construct = function() { this.name = "Tom"; }
var v = new Construct();
console.log("v.name = " + v.name);
return;
var Construct = function() { this.name = "Joe"; }
测试 1 的结果为:v.name = 乔
测试 1 的结果是:v.name = 汤姆
事实上,这篇文章不是关于 NodeJs,而是关于提升的(感谢 Alexey Ten)
很好的解释:
http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
在使用过C,C++,Java,PHP,Perl,Tcl,Python或GO等语言之后,我希望JavaScript在变量声明方面以相同的方式运行。如果在使用变量之前未声明变量,则根据语言:
- 你最终会得到一个错误。
- 变量的值未定义。
在 JavaScript 中,结果取决于变量的声明方式。请注意,变量的声明方式决定了其范围。提升意味着 JavaScript 会将所有变量的声明放在变量范围的开头。
var x; // Declaration
x = 10; // Initialization: this is the first time a value is affected to the variable.
x = 20; // Affectation.
换句话说:
(function() {
console.log("x = " + x + " f = " + f); // => x = undefined f = undefined
// Declaration + initialization
var x = 1;
var f = function() {};
})();
相当于:
(function() {
// Declaration
var x, f;
console.log("x = " + x + " f = " + f); // => x = undefined f = undefined
// initialization
x = 2;
f = function() {};
})();
这并不等同于:
(function() {
try {
console.log("x = " + x + " f = " + f);
// initialization
x = 2;
f = function() {};
} catch(e) {
console.log("ERROR: " + e.message); // => ERROR: x is not defined (and f is not defined either).
}
})();
但是,要小心!有一些微妙的问题:
(function() {
try {
console.log("x = " + x + " f = " + f);
x = 1;
f = function() {};
} catch (e) {
console.log("ERROR: " + e.message); // => ERROR: x is not defined (and f is not defined either).
}
})();
// x and f should be defined ???
console.log("x = " + x + " f = " + f); // => ReferenceError: x is not defined.
应该定义 x 和 f 吗?事实上,定义 x 和 f 的代码不会执行,因为 en 异常是在之前引发的。如果你试试这个:
(function() {
try {
x = 1;
f = function() {};
} catch (e) {
console.log("ERROR: " + e.message);
}
})();
console.log("x = " + x + " f = " + f); // => x = 1 f = function () {}
或:
(function() {
try {
console.log("x = " + x + " f = " + f); // => x = undefined f = undefined
x = 1;
f = function() {};
} catch (e) {
console.log("ERROR: " + e.message);
}
})();
console.log("x = " + x + " f = " + f); // => x = 1 f = function () {}
var x = 10, f;