我有一个Java背景,希望在JavaScript中理解构造函数和this关键字。
我遇到了这段代码,看起来非常简单
var Mediator = ( function( window, undefined ) {
function Mediator() {
this._topics = {};
}
Mediator.prototype.subscribe = function mediatorSubscribe( topic, callback ) {
if( ! this._topics.hasOwnProperty( topic ) ) {
this._topics[ topic ] = [];
}
this._topics[ topic ].push( callback );
return true;
};
Mediator.prototype.unsubscribe = function mediatorUnsubscrive( topic, callback ) {
if( ! this._topics.hasOwnProperty( topic ) ) {
return false;
}
for( var i = 0, len = this._topics[ topic ].length; i < len; i++ ) {
if( this._topics[ topic ][ i ] === callback ) {
this._topics[ topic ].splice( i, 1 );
return true;
}
}
return false;
};
Mediator.prototype.publish = function mediatorPublish() {
var args = Array.prototype.slice.call( arguments );
var topic = args.shift();
if( ! this._topics.hasOwnProperty( topic ) ) {
return false;
}
for( var i = 0, len = this._topics[ topic ].length; i < len; i++ ) {
this._topics[ topic ][ i ].apply( undefined, args );
}
return true;
};
return Mediator;
} )( window );
// example subscriber function
var Subscriber = function ExampleSubscriber( myVariable ) {
console.log( myVariable );
};
// example usages
var myMediator = new Mediator();
myMediator.subscribe( 'some event', Subscriber );
myMediator.publish( 'some event', 'foo bar' ); // console logs "foo bar"
我看到构造函数在名为_topics
的对象中设置了一个属性我试图在一个简单的版本中复制相同的逻辑,只抽象构造函数来查看行为。
var x=(function(){function x(){console.log('asdf')} return x;})();
var y=new x()
我得到一个错误,undefined不是一个函数。
我正在IIFE中返回x,所以出了什么问题。
提前致谢
答案 0 :(得分:4)
JavaScript中的值是指函数的执行上下文。在JavaScript中有三个执行上下文;即全球,功能和评估。以下示例将有助于更好地理解这个概念。
全球背景:
在全局上下文中,这指的是窗口对象。
console.log(this) // Window
功能背景:
在JavaScript中,可以用五种不同的模式调用函数:方法调用,函数调用,构造函数调用,应用调用和调用调用。函数上下文中this的值取决于函数的调用方式。
方法调用:
在方法调用模式中,这指的是对象(调用该方法的对象)本身。在调用时,它的值被绑定到对象。
var foo = {
bar : function() {
console.log(this);
return this;
}
}
console.log(foo.bar()) // Object; that refers to foo
var foo = {
bar : function() {
return this;
}
}
console.log(foo === foo.bar()); // true; 'this' returned by bar is nothing but foo
功能调用:
在函数调用模式中,这指的是窗口对象。从更广泛的角度来看,甚至函数调用模式也只是方法调用模式。该函数的上下文是窗口。让我们考虑一下如下命名函数baz:
var baz = function() {
console.log(this);
}
在函数调用模式中,baz可以调用为:
baz(); // Window
然而,baz也可以被调用为:
window.baz(); // Window; as stated in method invocation pattern
所有全局变量(变量,对象,函数)都与窗口相关联,并且根据规范,当引用全局时,可以省略窗口引用。因此,window指的是函数调用模式中的全局上下文。
构造函数调用:
在构造函数调用模式中,当使用new运算符调用函数时,这将引用由函数创建并返回的新对象(假设没有显式的return语句)。
var Foo = function () {// By convention the constructor name starts with upper case letter
console.log(this); // Foo
}
以上代码可以解释为
var Foo = function () {// By convention the constructor name starts with upper case letter
// create a new object
// using the object literal
// var this = {};
console.log(this); // Foo, only when invoked as new Foo(); otherwise this will refer to Window
// return this;
}
关于构造函数需要说的更多,这将在一个单独的文章中讨论。
应用调用&amp;呼叫调用:
Apply和Call调用与处理参数的方式不同。但就此而言,这两种模式的行为方式都是一样的。在这两种模式的美妙之处在于,这可以设置为任何所需的背景。
var bar = {}
var qux = function () {
console.log(this);
}
qux.apply(bar) // Object; that refers to bar
qux.call(bar) // Object; that refers to foo
评估背景:
在评估环境中,这个值是指父母的背景。
eval('console.log(this)') // Window
var foo = {
bar : function() {
eval('console.log(this)')
}
}
foo.bar(); // Object; that refers to foo
提醒一句:人们应该避免使用eval,大多数JavaScript忍者和大师都认为“eval是邪恶的”。但是,我觉得eval太强大了,无法使用。利用不当会产生意想不到的结果,这可能非常可怕。