IIFE理解(function () { /*code*/ })()

函数声明

在JS中只要是function开头,则认为是函数声明,而函数声明后面不能直接加()进行直接调用

function a(){ /*code*/ }()            //编译错误

但是在function前加上一元运算符之后,却没有问题了

 +function( $ ) {
     /* jquery code*/
 })(window.jQuery);

函数表达式

通过函数表达式定义的函数可以是匿名的,也可以是命名的。当出错时,如果是命名函数表达式,堆栈跟踪会显示函数名,更容易寻找错误。

var res = function(){ /*code*/ }      //‘}’后面不用写分号

var res = function name(){ /*code*/ }      

立即调用函数表达式(IIFE)

定义: 创建一个函数,并立即执行它(使用括号),由于外部无法引用它内部的变量,因此在执行完后很快就会被释放,这种机制不会污染全局对象。

var q = (function test1(){
        var a = 10;
        return a;
    }()); //q存储的不是函数表达式,而是其返回值
q //10
a //undefined
var f = function test1(){
        var a = 10;
        return a;
    }; //此时为函数表达式,f是函数test1的一个引用
f //返回函数test1
f() //10

在JS中括号、一元运算符如+、-、!、&&等可以用来消除函数声明与函数表达式之间的歧义。但使用运算符可能改变返回值,因此推荐使用括号。下列语句可以执行

(function () { /* code */ } ()); // 推荐使用这个
(function () { /* code */ })(); // 但是这个也是可以用的
!function(){ /* code */ }();  //使用运算符需注意值的改变

回到开头的问题,为什么第二种写法可以:

首先需要了解的是,在一个表达式后面加上括号(),该表达式会立即执行,但是在一个语句(声明语句)后面加上括号(),是完全不一样的意思,他的只是分组操作符(grouping operator),分组操作符中需要包含表达式

当js编译器开始执行的时候,碰见function之后,看到它周围没有任何东西。于是就把function关键字解析成函数声明,声明语句后的()是一个分组操作符,而分组操作符中必须包含表达式,因此导致后面运行出错了。

我们只需要用一个括号把这个匿名函数包裹起来,或者前面使用如-,~,!,&&这种其它的一元操作符,目的是告诉解析器在这些特定操作符附近的是一个表达式,避免js编译器将function关键字解析成函数声明,然后代码就能够正常执行

IIFE与闭包

需要注意的是,IIFE与闭包并没有必然的联系,并不是所有的IIFE都是闭包,闭包也不等于IIFE。IIFE是在函数表达式之后加括号表示立即执行,而闭包则是内层函数调用了外层函数的变量

参考:
https://www.cnblogs.com/lvmylife/p/8302644.html
http://benalman.com/news/2010/11/immediately-invoked-function-expression/

第一个代码// ==UserScript== // @name 点击弹窗 // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match https://study.enaea.edu.cn/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @run-at document-end // @grant none // ==/UserScript== (function() { 'use strict'; window.setInterval(function(){ var v=document.getElementsByTagName('video'); for (var i=0;i<v.length;i++) { if(v[i].playbackRate!=3) {v[i].playbackRate = 3;} } },5000) window.setInterval(function(){ if($('button:contains(继续学习)').text()!='') $('button:contains(继续学习)')[0].click() },5000) // Your code here... })();第二个代码// ==UserScript== // @name 自动切换 // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match https://study.enaea.edu.cn/circleIndexRedirect.do?action=toNewMyClass&type=course&circleId=* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @run-at document-end // @grant none // ==/UserScript== (function() { 'use strict'; window.setInterval(function(){ location.href = location.href; var progressValues=document.getElementsByClassName('progressvalue'); //获取所有课程进度值 var startbuttons=document.getElementsByClassName('golearn ablesky-colortip saveStuCourse');//获取开始学习按钮 var isEnd=true; //遍历所有进度,查看已学习课程是否都学至进度100% for (var i = 0; i < progressValues.length; i++) { if(progressValues[i].textContent!='0%' && progressValues[i].textContent!='100%'){ isEnd=false; break; } } //若已学完当前课程,切换下一集播放 if(isEnd){ for (var j = 0; j < progressValues.length; j++) { if(progressValues[j].textContent=='0%'){ startbuttons[j].click(); break; } } } },3*60*1000) // Your code here... })();给我
03-31
检查以下代码有无错误有无冗余:<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>WebGIS的地图应用</title> <!-- 在head部分增加引用esri提供的样式表 --> <link rel="stylesheet" href="https://js.arcgis.com/3.45/esri/css/esri.css"> <!-- 增加一个script标签,在该标签中引入ArcGIS API for JavaScript,实现ArcGIS API for JavaScript的调用 --> <script src="https://js.arcgis.com/3.45/init.js"></script> <style> /* 通过style标签来设置html body mapDiv的样式 */ html, body, #mapDiv { padding: 0;/* 外边距 */ margin: 0;/* 内边距 */ width: 100%;/**/ height: 100%;/**/ } #legendDiv{ width:200px; height:600px; position:absolute !important; top:200px; left:10px; } </style> <script> require([ "esri/map", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/dijit/Scalebar", "esri/symbols/SimpleMarkerSymbol", "esri/toolbars/draw", "esri/graphic", "esri/layers/GraphicsLayer", "esri/Color", "esri/layers/FeatureLayer", "esri/InfoTemplate", "esri/renderers/UniqueValueRenderer", "esri/symbols/SimpleFillSymbol", "esri/dijit/Legend" ], function( Map, ArcGISDynamicMapServiceLayer, Scalebar, SimpleMarkerSymbol, Draw, Graphic, GraphicsLayer, Color, FeatureLayer, InfoTemplate, UniqueValueRenderer, SimpleFillSymbol, Legend ) { var map = new Map("mapDiv", { center: [-95.625,39.243],// 经纬度中心点 zoom:2, // 缩放级数 basemap: "hybrid" // 混合底图类型 }); //添加比例尺 var scalebar = new Scalebar({ map: map,// 参考底图,必选项 attachTo: "bottom-left", // 指定比例尺在地图上的左下角 scalebarStyle:"line",// 比例尺类型,比例尺以线性显示 scalebarUnit: "english",// 比例尺单位 }); // 声明一个draw工具条 var toolBar = new Draw(map); // 绑定激活绘图工具的函数 function activate_tool() { // 根据class获取所有按钮 var btns = document.getElementsByClassName('btn-info'); console.log('btns',btns) for(var i = 0; i < btns.length; ++ i) { var type = btns[i].getAttribute('aria-label'); // 绘制点 if (type === "POINT") { btns[i].onclick = function() { toolBar.activate(Draw.POINT) }; // 结束绘制 } else if (type === "disabledraw") { btns[i].onclick = function() { toolBar.deactivate(); } } }}; // 调用函数 activate_tool(); // 为声明的draw工具添加了一个draw-complete事件,绘图结束后将图形显示在地图上 toolBar.on("draw-complete", drawEndEvent) function drawEndEvent(evt) { var geometry=evt.geometry; console.log("geometry",geometry) var type=geometry.type; console.log("type",type) // 创建点符号 var pointSymbol = new SimpleMarkerSymbol( SimpleMarkerSymbol.STYLE_TRIANGLE,//点的形状 20,//点的大小 null,//轮廓线的样式 new Color([255,0,127,0.5])//点的颜色 ); // 添加图形到地图 var graphic=new Graphic(geometry,pointSymbol); var graphicslayer=new GraphicsLayer(); graphicslayer.add(graphic); map.addLayer(graphicslayer); } var featurelayer=new FeatureLayer('https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/2',//必选参数 { mode:FeatureLayer.MODE_SNAPSHOT,//指定构造要素图层时显示的模式 outFields:["*"],//指定返回的数据值,*表示返回所有值 infoTemplate:new InfoTemplate(" ", "${sub_region}"), } ) var defaultSymbol=new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_NULL); //声明独立值专题图 var renderer = new UniqueValueRenderer( defaultSymbol, //默认符号 "sub_region"//渲染器用于匹配值的属性字段 ); //为独立值指定不同的符号 renderer.addValue("Pacific",new SimpleFillSymbol().setColor(new Color([255,0,0,0.5]))) renderer.addValue("Mtn",new SimpleFillSymbol().setColor(new Color([255,128,0,0.5]))) renderer.addValue("N Eng",new SimpleFillSymbol().setColor(new Color([255,255,0,0.5]))) renderer.addValue("S Atl",new SimpleFillSymbol().setColor(new Color([0,255,0,0.5]))) renderer.addValue("Mid Atl",new SimpleFillSymbol().setColor(new Color([0,255,255,0.5]))) renderer.addValue("E N Cen",new SimpleFillSymbol().setColor(new Color([0,0,255,0.5]))) renderer.addValue("W N Cen",new SimpleFillSymbol().setColor(new Color([128,0,128,0.5]))) renderer.addValue("E S Cen",new SimpleFillSymbol().setColor(new Color([75,0,130,0.5]))) renderer.addValue("W S Cen",new SimpleFillSymbol().setColor(new Color([138,43,226,0.5]))) //调用要素图层的setRenderer的方法,生成专题图 featurelayer.setRenderer(renderer) //将要素图层添加到地图 map.addLayer(featurelayer) //添加图例 var legend = new Legend({ map: map, layerInfos:[{ //layerInfos是个对象,指定地图中要显示在图例中的图层的子集 layer:featurelayer, //添加到图例中的图层 title:"美国各区域分布图例" //指定图层标题 }] }, "legendDiv"); legend.startup(); }); </script> </head> <body> <button class='btn-info' aria-label="POINT">点</button> <button class='btn-info' aria-label="disabledraw">结束绘制</button> <div id="mapDiv"></div> <div id="legendDiv"></div> </body> </html>
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值