在Javascript

时间:2015-08-21 18:02:22

标签: javascript

我不是在用JavaScript创建对象和添加/扩展方法。我知道一切都是一个对象和函数作为构造函数的使用,但我不太了解原型并创建/调用新方法。

var c1 = {
    name: "Neil",
};

var c2 = function() {
this.name = "Neil";
};

以上两点我都可以添加新内容:

c1.town = "a town";
c2.town = "a town";

c1.setTown = function(newTown) { this.town = newTown;};
c2.setTown = function(newTown) { this.town = newTown;};

我失败的地方是功能方法,我可以这样做:

c2.prototype.setTown2 = function(newTown) { this.town = newTown;};
c3 = new c2();
c3.setTown2("new3");

1:setTown和setTown2之间的区别是什么?为什么c3可以调用c3.town =“x”和c3.setTown2(“x”)但不能调用c3.setTown(“x”); ?

2:我似乎无法访问c1的“原型”(文字构造函数方法),为什么会这样?

感谢。

3 个答案:

答案 0 :(得分:1)

这是因为c1之类的JavaScript文字构造函数创建了一个实际的Object,而this之类的c2函数创建了可用于创建对象的构造函数。与c3。这是通过JavaScript注释对您的代码进行的分析:

//This is a literal object with property name equal to "Neil":
var c1 = {
    name: "Neil",
};
//We do not need to access the prototype here because c1 is an object, not a constructor:
console.log(c1.name);

//This is a constructor that creates an object with property name of "Neil".
var c2 = function() {
    this.name = "Neil";
};

//This creates a property town of "a town" on c1. This works because c1 is a regular object.
c1.town = "a town";
//This creates a property town of "a town" on c2. However, if you create an object with c2, the object will not inherit town because it is not on the prototype.
//This does not throw an error because even though c2 is a function, you can still set the property town on it because this property is what's called a _static property_. Static properties are properties that are set without the prototype like the property below:
c2.town = "a town";
//With c1, we do not need to access prototype because it's a regular object and with c2, we do not need to access prototype because it's a static property.
console.log(c1.town, c2.town);

//This works the same as above, except now, we're using functions instead of regular properties.
c1.setTown = function(newTown) { this.town = newTown;};
c2.setTown = function(newTown) { this.town = newTown;};
//This sets the town property of c1 like with a regular object:
c1.setTown("HI!");
//This sets the static property town of c2 because "this" in the static method c2.setTown is c2, so "this.town" is "c2.town", or the static property town which we set above:
c2.setTown("HI!");
//Both of the following outputs "HI!" because of the .setTown() calls above.
console.log(c1.town, c2.town);

//This method is set on the prototype of c2, meaning that objects made with c2 will inherit this method.
c2.prototype.setTown2 = function(newTown) { this.town = newTown;};

//This is an object made with the constructor c2. It inherits name because of the actual constructor function and it inherits setTown2 from the prototype. However, it does NOT inherit c2.town and c2.setTown because those are static properties not on the prototype.
c3 = new c2();
//This sets the town property of c3 because c3 inherited the setTown2 method from c2.prototype, so that method now sets the properties of c3.
c3.setTown2("new3");
//c3.name outputs "Neil" because of the c2 constructor function and c3.town outputs "new3" because of the above c3.setTown2() call:
console.log(c3.name, c3.town);

答案 1 :(得分:1)

你熟悉继承吗?编程中的一个常见概念,就是在javascript中模拟继承的方法。

基本上,当您向原型中添加新方法或变量时,您可以修改对象的主要结构......所以,当您决定从修改'类创建新对象时(我知道JS中没有类),唯一保留的方法是原型中的那些。

更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

答案 2 :(得分:1)

  

1:setTownsetTown2

之间有什么区别?

它们都是函数,但是每次要将其添加为方法时都会创建一个新函数,而prototype会自动继承它:

var c3 = new c2();
var c4 = new c2();

c3.setTown = function(newTown) { this.town = newTown;};
c4.setTown = function(newTown) { this.town = newTown;};

console.log(c3.setTown === c4.setTown) // false
console.log(c3.setTown2 === c4.setTown2) // true 

此外,setTown是对象c3c4的属性,其中setTown2不是。它是继承的。这意味着:

console.log(c3.hasOwnProperty("setTown")); // true
console.log(c3.hasOwnProperty("setTown2")); // false

因此Object.keys不会返回setTown2;但是如果你执行for…in循环,你将获得自己的属性和继承的属性。

  

为什么c3可以调用c3.town =“x”

因为您只是添加了一个属性。除非对象为frozensealed,否则您可以随时添加所需的任何属性。您也可以添加c3.foo = "bar",即使它不在原型中或添加到构造函数中。

  

和c3.setTown2(“x”)但不调用c3.setTown(“x”);

因为它是一个继承的方法,所以对象可以获得它遍历原型的链;但是你永远不会将setTown添加到c3实例,或添加到其原型链中的任何对象。

  

2:我似乎无法访问c1的“原型”(文字构造函数方法),为什么会这样?

因为prototype只是函数的属性,所以可以用作构造函数。 c1已经是一个对象,因此不需要将另一个对象作为“原型”。您可以直接使用c1作为对象的原型来创建基于它的其他对象:

var cc1 = Object.create(c1);

这将继承c1所有的方法和属性,所以:

console.log(cc1.name) // "Neil"
console.log(cc1.hasOwnProperty("name")) // false

正如我们在第一点看到的那样。

希望它有所帮助。