javascript构造函数如何工作

时间:2018-01-12 22:49:44

标签: javascript

我正在为初学者阅读MDN Javascript,并且它说你可以创建一个构造函数,然后根据该构造函数创建对象实例。现在,您可以访问构造函数中定义的属性和方法。然而,他们接着说,只有构造函数原型属性上定义的属性和方法才可用于对象实例,至少我理解。有人可以清除这一点,因为实例似乎可以访问这些实例,并且示例中没有定义原型属性。谢谢

function Person(first, last, age, gender, interests) {
    this.name = {
        first,
        last
    };
    this.age = age;
    this.gender = gender;
    this.interests = interests;
    this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + 
              ' is ' + this.age + ' years old.'+
              ' He likes ' + this.interests[0] +
              ' and ' + this.interests[1] + '.');
        };
        this.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
        };
    }

    var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);

    person1['age']
    person1.interests[1]
    person1.bio()
    // etc.

4 个答案:

答案 0 :(得分:3)

附加到构造函数的prototype属性的任何内容都是使用构造函数创建的所有实例之间的共享。所有这些对象的值都相同。

构造函数还可以将单个属性附加到正在创建的对象。这些特定于新实例,不会共享。

答案 1 :(得分:2)

因此,Javascript对象的工作方式与其他编程语言不同。好吧,无论如何,大多数主流的。

这里的交易 - 一个Javascript对象实际上只是一个字典(又名地图)。例如:

var x = {}; // creates a new blank object
x.something = 42; // creates a property on the object and assigns value to it
x['something'] = 15; // Alternate syntax. Assigns to the same property we just created.
x['yo, this is valid too!'] = true; // Yes, this is valid too.

明白我的意思?它只是一本字典,你可以设置你想要的任何东西。并且也没有设置 - 这是delete运算符的作用。

那么那些构造函数和原型呢?好吧,任何函数都可以用作构造函数。当你去的时候

var x = new foo();

真正发生的是Javascript创建一个新的空白对象,然后在将新创建的对象放入foo()时调用this。而且,看起来它有点像构造函数。

实际上有一点需要提及的怪癖。如果构造函数return是一个值,那么Javascript使用它而不是新创建的对象。所以,如果你这样做:

function foo() {
    this.meaning = 42;
}

var a = new foo();

然后a将包含Javascript为您创建的空白对象。但如果你这样做:

function foo() {
    this.meaning = 42;
    return {nope: 3};
}

var a = new foo();

然后a将包含{nope : 3}对象。好的,但很少使用。

无论如何,我们在哪里?啊,是的,原型。哦,等等,首先需要解释另一件事。在Javascript 一切是一个对象。所以,就像这些事情完全有效:

var a = 42;
var b = "hello, world";

a.foo = "yay";
b.bar = 10;

而且,只是为了真正打动你的想法,功能也是对象。一流的公民,可以这么说。这都是有效的:

function foo() {
}

foo.bar = "baz";

var x = foo;

是的,您可以像处理任何其他对象一样处理函数。您可以将它们放在变量中,将它们传递给参数中的其他函数,为它们分配和删除任意属性,然后命名它们。这是其他语言中很少见到的功能,所以它可能是最难解决的问题。我知道当我第一次明白这一点时,我的思绪就被吹了。

现在我们可以谈论原型。你看,Javascript中的每个函数都有一个叫做prototype的特殊魔法属性。默认情况下,它设置为空白对象。但您可以将其设置为另一个对象。或者,您可以向现有空白对象添加/删除属性。它只是另一个对象,没什么好看的。

此外,Javascript中的每个对象都有一个名为__proto__的特殊魔法属性。请记住,当您致电new foo()时,会创建一个新对象并将其作为foo()传递给this?好吧,那个新对象的__proto__设置为当时的foo.prototype

现在假设你这样做:

function foo() {
    this.a = 42;
}

foo.prototype.b = 15;

var x = new foo();

如果您输入x.a,那么x就有这样的属性,一切都很好。但是,如果您输入x.b,那么x就没有这样的属性,而且这就是魔术发生的地方。 Javascript会自动检查是否有x.__proto__.b,如果有,则返回!如果没有,它会检查x.__proto__.__proto__.b等,直到它遇到__proto__ == null的对象,然后它放弃并返回undefined,因为没有这样的属性。

另一方面,当你现在这样做时:

x.b = "foobarbaz";

然后直接在b对象上创建x属性。原型保持不变。

这就是你如何创造"继承"在Javascript中。随着原型。它与典型的基于类的语言不同,但同样强大。

还有一些其他的细微差别和技巧可以提及,还有大量的例子可以帮助你理清这一切,但是......我今天已经没有果汁了。 :)这应该回答这个问题,并希望能更好地理解你正在阅读的其他教程。

答案 2 :(得分:0)

Jules是对的。

进一步详细说明: 你有这个构造函数。

function Person(first, last, age, gender, interests) {
    this.name = {
        first,
        last
    };
    this.age = age;
    this.gender = gender;
    this.interests = interests;
    this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
    };
    this.greeting = function() {
        alert('Hi! I\'m ' + this.name.first + '.');
    };
}

现在你可以创建它的实例......

var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
var person2 = new Person('Anne', 'Smith', 32, 'male', ['music', 'skiing']);

如果您访问原型并更改它,则每个其他实例也会进行此更改。

person1.__proto__.attrX = "Hello World"
alert(person2.attX)

所有这些Javascript原型继承起初可能会非常混乱,但实际上你几乎从不需要。我实际上甚至不推荐它,因为它很容易搞乱。例如,你可以想到在JS中更改基本数据类型的原型。例如:

Person.__proto__.arguments = "";

这非常非常糟糕。特别是如果你真的想这样做:

Person.prototype.arguments = "";

如果你不知道原型和__proto__之间的区别。 它们在不同的角度基本相同。

  • __ proto__是指实例的构造函数
  • 如果你在构造函数上使用它,
  • prototype会做同样的事情

但是因为构造函数本身是函数的一个实例,所以如果直接在构造函数上调用__proto__,你将始终引用函数的构造函数。因此,在函数构造函数上更改某些内容会改变使用JS的所有函数,如果您更改了诸如参数之类的函数的整数,这可能会产生干扰。如果你深入了解它会变得非常讨厌......但你可以避免这些事情。

答案 3 :(得分:0)

javascript object inheritance relationship

我昨天刚刚学会了javascript对象的继承关系,并根据this good description制作了一个图表。希望它对你有用。