Bootstrap IIFE

Bootstrap源码(具体请看《Bootstrap源码解析》)和其他jQuery插件经常看到如下的写法:

Js代码  

  1. +function ($) {
  2. }(window.jQuery);

这种写法称为:

IIFE (Imdiately Invoked Function Expression 立即执行的函数表达式)。

一步步来分析这段代码。

先弄清函数表达式(function expression)和 函数声明(function declaration)的区别:

函数表达式  Function Expression - var test = function() {};

函数申明     Function Declaration - function test() {};

函数表达式中的函数可以为匿名函数,也可以有函数名,但是该函数实际上不能直接使用,只能通过表达式左边的变量 a 来调用。

Js代码  

  1. var a = function(){
  2. alert(‘Function expression‘);
  3. }
  4. var b = new a();

函数声明时必须有函数名。

Js代码  

  1. function a(){
  2. alert(‘Function declaration‘);
  3. }
  4. a();

这是一个匿名函数

Js代码  

  1. function () {
  2. }

你也许注意到匿名函数在console下会报错。console的执行和报错如下:

function(){}

SyntaxError: Unexpected token (

通过一元操作符+变成了函数表达式。也可以使用 - ~ !等其他一元运算符或者括号,目的是为了引导解析器,指明运算符附近是一个表达式。以下是三种经典方式 :

Js代码  

  1. +function () {
  2. };
  3. (function () {
  4. });
  5. void function() {
  6. };

函数表达式通过 末尾的() 来调用并运行。就是一个IIFE。

Js代码  

  1. +function () {
  2. }();
  3. (funtion () {
  4. })();

代码性能

运算符:+加-减!逻辑非~位取反,返回NaN(Not A Number)。

“()”组运算符:返回表达式的执行结果undefined。

void:按运算符结合语句执行,返回 undefined。
这几种的性能对比结果:

可见+性能最差(在Firefox下差距更明显),其他几种都差不多。不过IIFE只执行一遍,对js执行效率的影响特别小,使用哪种还是看个人爱好。

传参,为了避免$与其他库或者模板申明冲突,window.jQuery 作为参数传递。

Js代码  

  1. +function (x) {
  2. console.log(x);
  3. }(3);
  4. +function ($) {
  5. }(window.jQuery);

使用IIFE的好处

总结有4点:提升性能、有利于压缩、避免冲突、依赖加载

1、减少作用域查找。使用IIFE的一个微小的性能优势是通过匿名函数的参数传递常用全局对象window、document、jQuery,在作用域内引用这些全局对象。JavaScript解释器首先在作用域内查找属性,然后一直沿着链向上查找,直到全局范围。将全局对象放在IIFE作用域内提升js解释器的查找速度和性能。

传递全局对象到IIFE的一段代码示例:

Js代码  

  1. // Anonymous function that has three arguments
  2. function(window, document, $) {
  3. // You can now reference the window, document, and jQuery objects in a local scope
  4. }(window, document, window.jQuery); // The global window, document, and jQuery objects are passed into the anonymous function

2、有利于压缩。另一个微小的优势是有利于代码压缩。既然通过参数传递了这些全局对象,压缩的时候可以将这些全局对象匿名为一个字符的变量名(只要这个字符没有被其他变量使用过)。如果上面的代码压缩后会变成这样:

Js代码  

  1. // Anonymous function that has three arguments
  2. function(w, d, $) {
  3. // You can now reference the window, document, and jQuery objects in a local scope
  4. }(window, document, window.jQuery); // The global window, document, and jQuery objects are passed into the anonymous function

3、避免全局命名冲突。当使用jQuery的时候,全局的window.jQuery对象 作为一个参数传递给$,在匿名函数内部你再也不需要担心$和其他库或者模板申明冲突。 正如James padolsey所说:

An IIFE protects a module’s scope from the environment in which it is placed.

4、通过传参的方式,可以灵活的加载第三方插件。(当然使用模块化加载更好,这里不考虑。)举个例子,如果a页面需要使用KindEditor,a.html引入kindeditor.js 和 a.js

你可能会这么写 a.js:

Js代码  

  1. $(function() {
  2. var editor
  3. KindEditor.ready(function(K) {
  4. editor = K.create(‘textarea[data-name="kindeditor"]‘, {
  5. resizeType : 1
  6. })
  7. })
  8. })

b页面不需要使用Kindeditor,没有引入kindeditor.js。但是在合并JS代码后,b页面也会执行a.js中的代码,页面报错Uncaught ReferenceError: KindEditor is not defined。也就是b页面执行了KindEditor,难道所有页面都要加载Kindeditor源文件?

可以这么修改a.js,将KindEditor变量参数化,通过给立即执行的函数表示式的参数赋值,那么其他页面都不需要加载Kindeditor源文件

Js代码  

  1. +function( KindEditor){
  2. var editor
  3. if(KindEditor){
  4. KindEditor.ready(function(K) {
  5. editor = K.create(‘textarea[data-name="kindeditor"]‘, {
  6. resizeType : 1
  7. })
  8. })
  9. }
  10. }(KindEditor || undefined)

IIFE最佳实践

反对使用IIFE的其中一个理由是可读性差,如果你有大量的JavaScript代码都在一段IIFE里,要是想查找IIFE传递的实际参数值,必须要滚动到代码最后。幸运的是,你可以使用一个更可读的模式:

Js代码  

  1. (function (library) {
  2. // Calls the second IIFE and locally passes in the global jQuery, window, and document objects
  3. library(window, document, window.jQuery);
  4. }
  5. // Locally scoped parameters
  6. (function (window, document, $) {
  7. // Library code goes here
  8. }));

这种IIFE模式清晰的展示了传递了哪些全局对象到你的IIFE中,不需要滚动到长文档的最后。

jQuery优化

一段看上去写法有点像的代码。大部分项目用这段代码做作用域,这段代码会在DOM加载完成时初始化jQuery代码。

Js代码  

  1. $(function(){
  2. });

这种写法等同于

Js代码  

  1. $(document).ready(function(){
  2. // 在DOM加载完成时初始化jQuery代码。
  3. });

区别于

Js代码  

  1. $(window).load(function(){
  2. // 在图片等媒体文件加载完成时,初始化jQuery代码。
  3. });

结合IIFE的最佳实践,更好的写法是,立即执行document ready

Js代码  

  1. +function ($) {
  2. $(function(){
  3. })
  4. }(window.jQuery)

最佳实践

Js代码  

  1. // IIFE - Immediately Invoked Function Expression
  2. +function(yourcode) {
  3. // The global jQuery object is passed as a parameter
  4. yourcode(window.jQuery, window, document);
  5. }(function($, window, document) {
  6. // The $ is now locally scoped
  7. // Listen for the jQuery ready event on the document
  8. $(function() {
  9. // The DOM is ready!
  10. }));

具体请看工程师,请优化你的代码

在Bootstrap和其他插件中经常看到如下写法:

Js代码

  1. +function ($) { "use strict";
  2. }(window.jQuery);

 关于字符串"use strict";请看严格模式

严格模式

博客分类:

1、介绍严格模式

2、严格模式影响范围

  • 变量:  var、delete、变量关键字
  • 对象: 只读属性、 对象字面量属性重复申明
  • 函数:参数重名、arguments对象、申明
  • 其他:this、eval、关键字...

严格模式

ECMAScript 5 引入严格模式(‘strict mode‘)概念。通过严格模式,在函数内部选择进行较为严格的全局或局部的错误条件检测,使用严格模式的好处是可以提早知道代码中的存在的错误,及时捕 获一些可能导致编程错误的ECMAScript行为。在开发中使用严格模式能帮助我们早发现错误。

设立"严格模式"的目的,主要有以下几个:错误检测、规范、效率、安全、面向未来

  - 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;

  - 消除代码运行的一些不安全之处,保证代码运行的安全;

  - 提高编译器效率,增加运行速度;

  - 为未来新版本的Javascript做好铺垫。

进入"严格模式"的编译指示(pragma),是下面这行语句:  

Js代码  

  1. "use strict";

这个语法从ECMAScript 3 开始支持。向后兼容不支持严格模式的浏览器,他们就当遇到了一个普通字符串,编译时忽略。

将"use strict"放在脚本文件的第一行,则整个脚本都将以"严格模式"运行。

如果这行语句不在第一行,则无效,整个脚本以"正常模式"运行。

如果不同模式的代码文件合并成一个文件,这一点需要特别注意。

(严格地说,只要前面不是产生实际运行结果的语句,"use strict"可以不在第一行,比如直接跟在一个空的分号后面。)

Js代码  

  1. <script>
  2. "use strict";
  3. console.log("这是严格模式。");
  4. </script>
  5. <script>
  6.  console.log("这是正常模式。");
  7. </script>

将"use strict"放在函数体的第一行,则整个函数以"严格模式"运行。

Js代码  

  1. function strict(){
  2. "use strict";
  3. return "这是严格模式。";
  4. }
  5. function notStrict() {
  6. return "这是正常模式。";
  7. }

建议只在特定的作用域中使用严格模式。放在全局作用域中(函数外部),页面的其他脚本也都处于严格模式下。因为上面的调用方法不利于文件合并,所以更好的做法是,下面的方法,将整个脚本文件放在一个立即执行的函数表达式IIFE之中。

Js代码  

  1. +function (){  "use strict";
  2. }();

变量

非严格模式下,a = 1可以创建一个全局变量。

严格模式下,变量都必须先用var命令显示声明,然后再使用。 严格模式不允许意外创建的全局变量(示例),否则会报错(Uncaught ReferenceError: v is not defined )。

Js代码  

  1. "use strict";
  2. v = 1; // 报错,v未声明
  3. for(i = 0; i < 2; i++) { // 报错,i未声明 ReferenceError
  4. }

而且,严格模式不能对变量调用 delete 操作符(示例),会导致错误(Uncaught SyntaxError: Delete of an unqualified identifier in strict mode. )。

非严格模式允许这样操作,但返回false 。

别用这些词做 变量名 或 参数名 implements, interface, let, package, private, protected, public, static, yield。这些都是保留字,将来ECMAScript 版本中可能会用到他们。

严格模式下作为其保留关键字,使用这些标识符作为变量名会导致语法错误。

Js代码  

  1. function package(protected){ // 报错!
  2. "use strict";
  3. var implements; // 报错!
  4. interface: // 报错!
  5. while (true){
  6. break interface; // 报错!
  7. }
  8. function private() { } // 报错!
  9. }
  10. function fun(static) { ‘use strict‘; } // 报错!

对象

为只读属性赋值报错(示例

Js代码  

  1. "use strict"
  2. var testObj = Object.defineProperties({}, {
  3. prop1: {
  4. value: 10,
  5. writable: false // by default
  6. },
  7. prop2: {
  8. get: function () {
  9. }
  10. }

对象字面量同一个属性重复赋值(Uncaught SyntaxError: Unexpected identifier),非严格模式会取最后一个(示例

Js代码  

  1. "use strict"
  2. var person = {
  3. name : "Tom"
  4. name : "Cat"
  5. }

 

另外两种情况:

为不可配置的属性使用delete操作符会抛出typeError

为不可扩展的对象添加属性会抛出TypeError

函数

严格模式下参数名不能重复(Uncaught SyntaxError: Strict mode function may not have duplicate parameter names)(示例

非严格模式,函数内部实际访问的是第二个参数,要访问第一个参数必须通过arguments对象。

Java代码  

  1. "use strict"
  2. function sum(num, num) {}

非严格模式下,修改命名参数值也会反映到arguments对象中,

严格模式下者两个值是完全独立的。(示例)

Js代码  

  1. "use strict"
  2. function showValue(value) {
  3. value = "Foo"
  4. alert(value)        // Foo
  5. alert(arguments[0]) // 严格模式 hi
  6. // 非严格模式 Foo
  7. }
  8. showValue("hi")

严格模式也淘汰了arguments.callee(引用函数本身)和arguments.caller(引用函数调用函数)

不允许非顶层的函数。也就是,只能在脚本的顶级和在函数内部申明函数,if for等语句中申明函数会导致语法错误。

Js代码  

  1. "use strict";
  2. if (true){
  3. function f() { } // 报错! syntax error
  4. f();
  5. }
  6. for (var i = 0; i < 5; i++){
  7. function f2() { } // 报错! syntax error
  8. f2();
  9. }
  10. function baz(){ // kosher
  11. function eit() { } // also kosher
  12. }

this

严格模式下抑制this。

(function(){ return this; })()

Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}

(function(){ ‘use strict‘; return this; })()

undefined

其他

去掉了with。

数字前面别加0。因为...禁用八进制算法。因为八进制不包含在ECMAScript中,数字前面的0会改变数字的含义,js会认为是一个八进制数,从而报错。

Js代码  

  1. "use strict";
  2. var sum = 015 + // 报错! syntax error
  3. 197 +
  4. 142;

还有其他例子

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FFunctions_and_function_scope%2FStrict_mode

参考资料:
http://msdn.microsoft.com/zh-cn/library/br230269(v=vs.94).aspx

时间: 2024-11-10 13:33:28

Bootstrap IIFE的相关文章

JavaScript学习总结(二)——闭包、IIFE、apply、函数与对象

目录 一.闭包(Closure) 1.1.闭包相关的问题 1.2.理解闭包 二.对象 2.1.对象常量(字面量) 2.2.取值 2.3.枚举(遍历) 2.4.更新与添加 2.5.对象的原型 2.6.删除 2.7.封装 三.函数 3.1.参数对象 (arguments) 3.2.构造函数 3.3.函数调用 3.3.1.call 3.3.2.apply 3.3.3.caller 3.3.4.Callee 3.5.立即执行函数表达式 (IIFE) 3.5.1.匿名函数与匿名对象 3.5.2.函数与函数

avaScript学习总结(二)——闭包、IIFE、apply、函数与对象 目录

一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div,for循环绑定事件. 示例代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> <style type="

Bootstrap按钮插件

前面的话 按钮插件提供了一组可以控制按钮多种状态的功能,比如按钮的禁用状态.正在加载状态.正常状态等.本文将详细介绍Bootstrap按钮插件 加载状态 通过按钮可以设计状态提示,当单击按钮时,会显示loading状态信息.例如,点击"加载"按钮,会触发按钮的加载的状态 通过添加 data-loading-text="Loading..." 可以为按钮设置正在加载的状态,但从 v3.3.5 版本开始,此特性不再建议使用,并且已经在 v4 版本中删除了 [注意]如果不

Bootstrap 源码解析

Bootstrap 源码解析 1.Bootstrap的作用域 2.Bootstrap的类定义 3.Bootstrap的插件定义 4.Bootstrap的事件代理 5.Bootstrap的对象数据缓存 6.Bootstrap的防冲突 7.作用域外如何使用Button类 8.Bootstrap的单元测试 Bootstrap的作用域 Bootstrap每个插件都定义在下面这段作用域代码中: 请看<IIFE>和<严格模式>编译环境. 在插件的作用域之外,全局范围执行代码的第一行,检测了jQ

Bootstrap 源码解析(转)

1.Bootstrap的作用域 2.Bootstrap的类定义 3.Bootstrap的插件定义 4.Bootstrap的事件代理 5.Bootstrap的对象数据缓存 6.Bootstrap的防冲突 7.作用域外如何使用Button类 8.Bootstrap的单元测试 Bootstrap的作用域 Bootstrap每个插件都定义在下面这段作用域代码中: +function ($) { ... }(window.jQuery) 请看<IIFE>和<严格模式>编译环境. 在插件的作用

IIFE

转自http://suqing.iteye.com/blog/1981591 介绍IIFE IIFE的性能 使用IIFE的好处 IIFE最佳实践 jQuery优化 在Bootstrap源码(具体请看<Bootstrap源码解析>)和其他jQuery插件经常看到如下的写法: 1 +function ($) { 2 3 }(window.jQuery); 这种写法称为: IIFE (Immediately Invoked Function Expression 立即执行的函数表达式). 一步步来分

Bootstrap模态弹出框

前面的话 在 Bootstrap 框架中把模态弹出框统一称为 Modal.这种弹出框效果在大多数 Web 网站的交互中都可见.比如点击一个按钮弹出一个框,弹出的框可能是一段文件描述,也可能带有按钮操作,也有可能弹出的是一张图片.本文将详细介绍Bootstrap模态弹出框 结构分析 Bootstrap框架中的模态弹出框,分别运用了“modal”.“modal-dialog”和“modal-content”样式,而弹出窗真正的内容都放置在“modal-content”中,其主要又包括三个部分: ? 

笔记:IIFE 立即执行的函数表达式 +function ($) { }(window.jQuery);

在Bootstrap源码(具体请看<Bootstrap源码解析1>)和其他jQuery插件经常看到如下的写法: +function ($) { }(window.jQuery); 这种写法称为:IIFE 2(Imdiately InvokedFunction Expression 立即执行的函数表达式). 解析: 先弄清函数表达式(function expression)3和 函数声明(function declaration)的区别: 函数表达式  var test = function()

Bootstrap + AngularJS+ Ashx + SQL Server/MySQL

去年年底12月,为适应移动端浏览需求,花了1个月时间学习Bootstrap,并将公司ASP网站重构成ASP.NET. 当时采取的网站架构: Bootstrap + jQuery + Ashx + SQL Server 时间紧,没人带,只能硬着头皮,最后如期完成,但是也遗留了几个问题. 问题: 1.页面查询条件太复杂,太多的checkbox,jQuery操作DOM虽然方便,但是组合成json提交给后端还是比较麻烦,有没有天然支持json的前端框架或者脚本语言? html控件做的任何修改,都自动保存