Javascript 咖喱
我是一名JavaScript新手,试图了解Oreilly JavaScript食谱中关于咖喱的教程 请有人用通俗易懂的语言一步一步地详细解释一下这个程序。请确保解释在程序最后第二行传递的“null”参数。如果您能提供帮助,请提前向您表示感谢Javascript 咖喱,javascript,Javascript,我是一名JavaScript新手,试图了解Oreilly JavaScript食谱中关于咖喱的教程 请有人用通俗易懂的语言一步一步地详细解释一下这个程序。请确保解释在程序最后第二行传递的“null”参数。如果您能提供帮助,请提前向您表示感谢 function curry(fn, scope) { scope = scope || window; var args = []; for (var i = 2, len = arguments.length; i < le
function curry(fn, scope) {
scope = scope || window;
var args = [];
for (var i = 2, len = arguments.length; i < len; ++i) {
args.push(arguments[i]);
}
return function() {
var args2 = [];
for (var i = 0; i < arguments.length; i++) {
args2.push(arguments[i]);
}
var argstotal = args.concat(args2);
return fn.apply(scope, argstotal);
};
}
function diffPoint(x1, y1, x2, y2) {
return [Math.abs(x2 - x1), Math.abs(y2 - y1)];
}
var diffOrigin = curry(diffPoint, null, 3.0, 4.0);
var newPt = diffOrigin(6.42, 8.0); //produces array with 3
功能咖喱(fn,范围){
范围=范围| |窗口;
var args=[];
for(变量i=2,len=arguments.length;i
函数curry
允许您将函数f
(函数curry
的第一个参数)转换为作用域c
(第二个参数),并带有可选的附加参数(其余参数)
这意味着此函数调用:
curry(func, scope);
返回一个函数newFunc
,其调用:
var newFunc = curry(func, scope); // get the new function
newFunc(); // now invoke it
相当于:
scope.func();
所有这些的净效果是关键字在func
中引用scope
*
具体示例时间 假设
scope
是一个简单的JS对象,只有一个属性:
var scope = {name: 'Inigo Montoya'};
而f
是一个函数,它想在范围内使用一些值
:
function f() {
return 'My name is ' + scope.name;
}
这样称呼它:
f(); // returns 'My name is Inigo Montoya'
var scope = { name: 'Inigo Montoya',
sayIt: f_new }
sayIt(); // returns 'My name is Inigo Montoya'
嗯,这是一种方法。它起作用了
另一种方法是使用curry
功能。f
不必知道引用scope
对象,scope
现在是函数的调用上下文。现在该函数可以使用这个关键字了
function f_new() {
return 'My name is ' + this.myName; // see the difference?
}
var sayIt = curry(f, scope);
现在,sayIt
是一个不关心调用什么scope
的函数。就像sayIt
是在scope
对象上定义的,如下所示:
f(); // returns 'My name is Inigo Montoya'
var scope = { name: 'Inigo Montoya',
sayIt: f_new }
sayIt(); // returns 'My name is Inigo Montoya'
…除了这不是范围
的实际定义sayIt
就是这样。现在,我们可以调用sayIt
,如下所示:
f(); // returns 'My name is Inigo Montoya'
var scope = { name: 'Inigo Montoya',
sayIt: f_new }
sayIt(); // returns 'My name is Inigo Montoya'
还和我在一起吗?
呸。所有这些的要点是,在您的示例中,null
被提供作为运行它的diffOrigin
的作用域,因为它不关心作用域中的内容。行(在curry
)scope=scope | |窗口中
意味着,如果范围
是一个伪值(即null
是),那么新函数(diffOrigin
在本例中)将在全局范围内执行:此
将引用窗口
这对你有意义吗?
*它被称为“调用上下文”//定义curry()函数
功能咖喱(fn,范围){
//如果未传入任何范围,请将范围设置为window(默认全局对象)。
范围=范围| |窗口;
//将参数转换为普通数组,因为它不是一个数组。
//args将包含所有额外参数,不包括前2个(fn,作用域)
//循环从索引2开始,以i=2跳过fn和scope
var args=[];
for(变量i=2,len=arguments.length;i
在这种情况下,根本不使用范围
参数<代码>范围
设置此
对象的内容。您正在使用的函数没有使用此,因此没有实际效果。当调用fn.apply(scope,args)
时,就会设置作用域,这既可以设置要运行的作用域,也可以提供要传入的参数。如果您不介意建议,请从Javascript开始:好的部分。接下来是Javascript模式,或者Javascript忍者的秘密,以获得更高级的技术。烹饪书更多的是用来解决问题,而不是学习资源
马特·鲍尔解释得很好。如果你是一个初学者,不管怎样,我都不会费力去弄清楚咖喱的功能。除此之外,在我看来,这种咖喱功能很糟糕。这就是我要改变它的方式
// this is doing binding and partial function application,
// so I thought bind was a more appropriate name
// The goal is that when you execute the returned wrapped version of fn, its this will be scope
function bind(fn, scope) {
// arguments is an implicit variable in every function that contains a full list
// of what was passed in. It is important to note that javascript doesn't enforce arity.
// since arguments is not a true array, we need to make it one.
// a handy trick for this is to use the slice function from array,
// since it will take arguments, and return a real array.
// we are storing it in a variable, because we will need to use it again.
var slice = Array.prototype.slice,
// use slice to get an array of all additional arguments after the first two
// that have been passed to this function.
args = slice.call(arguments, 2);
// we are returning a function mostly as a way to delay the execution.
// as an aside, that this is possible in a mainstream language is a minor miracle
// and a big part of why i love javascript.
return function() {
// since functions are objects in javascript, they can actually have methods.
// this is one of the built in ones, that lets you execute a function in a different
// context, meaning that the this variable inside the
// function will actually refer to the first argument we pass in.
// the second argument we are jamming together the arguments from the first function
// with the arguments passed in to this wrapper function, and passing it on to fn.
// this lets us partially apply some arguments to fn when we call bind.
return fn.apply(scope, args.concat(slice.call(arguments)));
}
}
JavaScript虽然很棒,但却非常冗长。在定义绑定时不必要地重复var只会增加很多噪音。而且,没有必要费力地构建这样一个真正的阵列,sli