不了解在Javascript中使用新关键字

时间:2013-01-14 07:01:30

标签: javascript prototype new-operator

下面的代码片段来自O'Reilly的“Javascript Web Applications”。在其中,作者解释说使用new关键字通常会返回this上下文,除非您特别返回其他内容 - 下面,他将返回'一个将设置新类的函数',他的话(第7页):

var Class = function(){
    var klass = function(){
        this.init.apply(this, arguments);
    };
    klass.prototype.init = function(){};
    return klass;
};

var Person = new Class;

Person.prototype.init = function(){
    // Called on Person instantiation
};

// Usage:
var person = new Person;

我不是这样做的。返回klass在这做什么?在var Person = new Class的情况下,我没有得到一个新的Class对象,而是一些可以创建一个Class的函数?这就是我从文中读到的内容,但这让我感到困惑。

4 个答案:

答案 0 :(得分:6)

在到达目的地之前,第一步是this

this通常可以指出三件事。 如果你有一个函数,它是一个对象的属性:

var Bob = {
    name : "Bob",
    say  : function () { console.log(this.name); }
};

Bob.say(); // "Bob"

在这种情况下,this指向拥有该属性的任何对象(无论前面是一个点,在函数被调用的那一刻)

var say = Bob.say; // passing the function to a variable
var Sam = { name : "Sam" };
Sam.say = Bob.say; // passing the function to an object's property

say(); // undefined -- not what you were expecting
Sam.say(); // "Sam"

所以this是在最后一秒决定的。

函数也具有自己的属性,如对象 其中两个是名为.call.apply的函数,它们允许您运行该函数,但告诉函数确切地说this是什么。

还记得say();如何独立运作吗?

var say = Bob.say;
say.call(Bob); // "Bob" -- hooray!

this的下一部分是我们在面向对象语言中最常用的部分;使用thisnew创建类的新实例:

var Person = function (name) {
    this.name = name;
    this.say = function () { console.log(this.name); };
};

var bob = new Person("Bob");
bob.say(); // "Bob"

基本上,在这个构造函数内部(或任何函数,因为构造函数在JS中并不特殊),函数首先检查是否调用了new
如果是,请将this设置为一个全新的对象,无论它是否是对象的一部分:

var Creatures = {};
Creatures.Person = Person;

Creatures.Person("Bob"); // `this` === Creatures
Creatures.name; // "Bob" -- whoops
var bob = new Creatures.Person("Bob");
bob.say(); // "Bob", yay!

所以就像函数在函数顶部说if (new) { this = {}; }一样。

我说有三种可能性 第三是this === window
如果使用this不是对象的函数(通过调用/ apply或作为对象的属性)并且new未用于创建新对象,则{{1点this
这就是为什么window以前不能独立工作的原因; say();是等效的。

返回window.say();一秒钟 - new会做其他一些事情 即,它设置对象的构造函数的值:

new

它还为从该构造函数构成的对象提供对所有实例共享的var bob = new Person(); bob instanceof Person; // true 对象的访问权限。

现在,看看Class / Klass里面发生了什么:
我们正在创建一个prototype对象 在new Class();函数内部,Class(由于this = {};) 然后,我们正在创建一个新的“构造函数”函数new

然后,我们正在设置原型klass函数,我们init.apply的任何新this,在调用新实例时)。

然后我们回到了klass。

klass实际上就是你在创建一个新类时所调用的内容

当你要求一个类的新对象时,正在运行klass。

希望对klassnew以及this.call提供帮助。

答案 1 :(得分:3)

在javascript中,new关键字会隐式返回this

如果您有function Foo () {}并申请new Foo,则javascript会执行function Foo () { return this; }。他通过显式返回另一个对象(klass对象)来覆盖javascript' new的工作方式。

看看这个例子。

function Foo () { this.name = "foo"; };

function Bar () {
    return new Foo; 
};

var bar = new Bar;  // bar is now a Foo, because of the explicit return.

bar.name //=> 'foo'

如果你可以遵循,那么你可以按照他正在做的事情。

当你说var Person = new Class时,它实际上是返回klass函数并将其存储在Person变量(指针)中。

答案 2 :(得分:1)

遵循作者的逻辑:

  

使用new关键字通常会返回this上下文,   除非您特别返回其他内容

如果他/她是正确的,那么以下代码:

var Class = function(){
    var klass = function(){
        this.init.apply(this, arguments);
    };
    klass.prototype.init = function(){};
    return klass;
};

没有定义“类”类;相反,它定义了一个“基础”,当new时,而不是返回实例,将返回一个私有定义的,当{{1我们将保证运行new方法(init())。

通过这种方式,

this.init.apply(this)

您正在创建名为var Person = new Class; 的新,它遵循Personklass定义为Class的约束和行为(如果有)在“真正的”OOP中看起来像extend / inherit

以下代码

Person.prototype.init = function(){
// Called on Person instantiation
};

实际上是为 Person定义“构造函数”。

修改

很抱歉昨天没有提出正确的单词和句子。我擅长表达。

如果您对OOP感到满意,可以想象Class是一个接口/抽象/虚拟类,当您new Class时,而不是< em>创建一个实例,而不是在Class内私有/虚拟定义的扩展/继承/实现行为。

klass.prototype.init=function(){};类似于JS的抽象/虚函数方式,通过组合this.init.apply(this),您可以在可能的层面上将其想象为构造函数。

答案 3 :(得分:0)

实际上,这里var Person = new Class; new关键字仅用于触发Class函数,所以基本上你可以像var Person = Class();这样使用,它会有相同的结果