下面的代码片段来自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的函数?这就是我从文中读到的内容,但这让我感到困惑。
答案 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
的下一部分是我们在面向对象语言中最常用的部分;使用this
和new
创建类的新实例:
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。
希望对klass
和new
以及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;
的新类,它遵循Person
内klass
定义为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();
这样使用,它会有相同的结果