了解 IIFE
Understanding IIFE
在我的页面中,我有几个 img 标签如下:
<img class="img-fluid meeseks" src="img/meeseks_red.jpg" data-color="#ee5b61" />
在我创建的 js 文件中:
function Store(path,color){
this.path=path
this.color=color}
然后,开始编写代码,我这样写:
img_path=[]
for (var i=0;i<img.length;i++){
img_path.push( new Store(img[i].getAttribute("src"),img[i].getAttribute("data-color")))
}
获取一个对象数组,存储每个图像的src和颜色。
现在,在研究 IIFE,我写的这个似乎也有效:
(function store_inf(){
img_path=[]
for (var i=0;i<img.length;i++){
img_path.push( new Store(img[i].getAttribute("src"),img[i].getAttribute("data-color")))
}
return img_path
})()
在这种情况下哪种方式更好?我还注意到,如果我省略 return 一切正常(如果我记录 img_path 数组,我总是有一个对象数组)
那么 IIFE return 是一个永久数组,即使在调用 IIFE 之后,在全局范围内也是如此?
谢谢
之所以img_path
是全局的,与IIFE无关。它是全局的,因为您尚未使用 var
关键字声明它。未使用 var
(或 const
或 let
)声明的所有内容都将附加到全局范围,在您的情况下它将附加到 window
对象。只需在您的 IIFE(或非 IIFE)代码版本之后尝试 console.log(window.img_path)
。
我建议您开始在您的 js 中使用 use strict
,因为它会指出更多 "unobvious" 错误。
您当前的代码可以工作,因为 img_path 实际上是 全局的 而您的 IIFE 是无用的。你可以这样做:
var img_path=(function(){
var img=document.getElementByTagName("img");
var img_path=[];//now local
for (var i=0;i<img.length;i++){
img_path.push( new Store(img[i].getAttribute("src"),img[i].getAttribute("data-color")))
}
return img_path
})()
现在有一个封闭的 img_path 和 img 数组以及一个全局 img_path。
请注意,您还可以这样做:
var img_path=document.querySelectorAll("img").values().map(el=>new Store(el.src,el.getAttribute("data-color")));
你应该多关心一下分号,它们不是用来消遣的,而是因为你需要它们。在某些边缘情况下,会在没有分号的情况下引入歧义。也就是说,如果您不以任何方式(作为参数或赋值)使用结果,则不需要函数 namen 并且不需要 return 任何东西。你也不需要 store 函数,它真的没什么用,只需使用 JS 对象字面量,如下所示。函数也可以写成:
(function () {
"use strict";
var i, img_path;
img_path = [];
for (i = 0; i < img.length; i++)
{
img_path.push({
"path": img[i]["src"],
"color": img[i]["data-color"]
});
}
// TODO: use img_path here because outside this function scope it does not exist
}());
// ^ better parens placement
有关如何编写干净代码和坚持开源 JS 风格的更多信息,请查看 JSLint 和类似工具。您会看到此类工具给您带来了多少样式错误。
这里的 IIFE 并不是真正让您大吃一惊的部分。
在 JavaScript 中,您必须声明您的变量。如果你在浏览器中使用 JS,并且你没有使用严格模式(你应该是,一旦你更好地掌握了这门语言),你就会知道为什么会发生这些事情。
var x = 1;
function makeGlobalsHappen () {
y = 2;
var z = 4;
}
makeGlobalsHappen();
x; // 1
y; // 2
z; // ERROR! z is not defined
这与 IIFE 无关(其中,我有 none)。
我是选择加入 ES5 的严格模式,还是使用现代 JS 模块(设计严格):
const x = 1;
const makeGlobals = () => {
y = 2; // ERROR! y is undefined
const z = 4;
};
makeGlobals(); // *BOOM*
在我的页面中,我有几个 img 标签如下:
<img class="img-fluid meeseks" src="img/meeseks_red.jpg" data-color="#ee5b61" />
在我创建的 js 文件中:
function Store(path,color){
this.path=path
this.color=color}
然后,开始编写代码,我这样写:
img_path=[]
for (var i=0;i<img.length;i++){
img_path.push( new Store(img[i].getAttribute("src"),img[i].getAttribute("data-color")))
}
获取一个对象数组,存储每个图像的src和颜色。
现在,在研究 IIFE,我写的这个似乎也有效:
(function store_inf(){
img_path=[]
for (var i=0;i<img.length;i++){
img_path.push( new Store(img[i].getAttribute("src"),img[i].getAttribute("data-color")))
}
return img_path
})()
在这种情况下哪种方式更好?我还注意到,如果我省略 return 一切正常(如果我记录 img_path 数组,我总是有一个对象数组)
那么 IIFE return 是一个永久数组,即使在调用 IIFE 之后,在全局范围内也是如此? 谢谢
之所以img_path
是全局的,与IIFE无关。它是全局的,因为您尚未使用 var
关键字声明它。未使用 var
(或 const
或 let
)声明的所有内容都将附加到全局范围,在您的情况下它将附加到 window
对象。只需在您的 IIFE(或非 IIFE)代码版本之后尝试 console.log(window.img_path)
。
我建议您开始在您的 js 中使用 use strict
,因为它会指出更多 "unobvious" 错误。
您当前的代码可以工作,因为 img_path 实际上是 全局的 而您的 IIFE 是无用的。你可以这样做:
var img_path=(function(){
var img=document.getElementByTagName("img");
var img_path=[];//now local
for (var i=0;i<img.length;i++){
img_path.push( new Store(img[i].getAttribute("src"),img[i].getAttribute("data-color")))
}
return img_path
})()
现在有一个封闭的 img_path 和 img 数组以及一个全局 img_path。
请注意,您还可以这样做:
var img_path=document.querySelectorAll("img").values().map(el=>new Store(el.src,el.getAttribute("data-color")));
你应该多关心一下分号,它们不是用来消遣的,而是因为你需要它们。在某些边缘情况下,会在没有分号的情况下引入歧义。也就是说,如果您不以任何方式(作为参数或赋值)使用结果,则不需要函数 namen 并且不需要 return 任何东西。你也不需要 store 函数,它真的没什么用,只需使用 JS 对象字面量,如下所示。函数也可以写成:
(function () {
"use strict";
var i, img_path;
img_path = [];
for (i = 0; i < img.length; i++)
{
img_path.push({
"path": img[i]["src"],
"color": img[i]["data-color"]
});
}
// TODO: use img_path here because outside this function scope it does not exist
}());
// ^ better parens placement
有关如何编写干净代码和坚持开源 JS 风格的更多信息,请查看 JSLint 和类似工具。您会看到此类工具给您带来了多少样式错误。
这里的 IIFE 并不是真正让您大吃一惊的部分。
在 JavaScript 中,您必须声明您的变量。如果你在浏览器中使用 JS,并且你没有使用严格模式(你应该是,一旦你更好地掌握了这门语言),你就会知道为什么会发生这些事情。
var x = 1;
function makeGlobalsHappen () {
y = 2;
var z = 4;
}
makeGlobalsHappen();
x; // 1
y; // 2
z; // ERROR! z is not defined
这与 IIFE 无关(其中,我有 none)。
我是选择加入 ES5 的严格模式,还是使用现代 JS 模块(设计严格):
const x = 1;
const makeGlobals = () => {
y = 2; // ERROR! y is undefined
const z = 4;
};
makeGlobals(); // *BOOM*