1月 03
Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

Vue.js 自身不是一个全能框架——它只聚焦于视图层。因此它非常容易学习,非常容易与其它库或已有项目整合。另一方面,在与相关工具和支持库一起使用时,Vue.js 也能完美地驱动复杂的单页应用。

页面首先需要引用vue.js

    <script src="https://cdn.bootcss.com/vue/2.5.13/vue.min.js"></script>

一个最简单的例子

    <div id="app">
        <p>{{ message }}</p>
        <input v-model="message">
    </div> 
    <script>
        new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue.js!'
            }
        }) 
    </script>

written by ocean

5月 18

 AngularJS中,通常需要注册一个module,然后为module在注册controller等。AngularJS不仅仅有angular.js文件,还有其他的js文件,比如用来做路由配置的angular-route.js文件等,每一个文件包含module,使用AngularJS的过程就是让这些modules协同工作的过程。

 

首先在页面引入AngularJS的核心js文件:

<script src="angular.min.js"></script>

接着,在定义js文件中为当前页面注册一个module:

var myApp = angular.module("helloApp",[])

以上,module的名称为helloApp, []数组用来存放与当前module有依赖关系的其它modules,比如['ngRoute','….']。

然后,为module注册controller。

    myApp.controller("TestController",['$scope',function($scope){
        $scope.hello = "Hello World!";
    }]);

 以上,controller()的第一个参数是controller的名称,第二个参数的数组,数组的最后一个元素一定是匿名函数,其它元素是AngularJS的全局service,或者说是全局对象。需要注意的是:数组中的全局service的位置和名称必须和匿名函数的形参一一对应。

我们还可以这样写:

myApp.controller("TestController", function($scope){
    $scope.hello = "Hello World!";  
});

不过,以上的写法在给js文件优化压缩的时候,会改变$scope变量的名称,比如替代为a,由于AngularJS只认$scope不认识a,这样会导致报错。所以,这种方法不推荐。

另外,全局service是以注入的方式被当前controller所使用。在AngularJS中,很多全局service都是通过依赖注入的方式被运用。

 

最后,页面中要做3件事情。

1、使用ng-app声明当前module的名称

<html ng-app="helloApp">

2、使用ng-controller声明需要使用的controller

<body ng-controller="TestController">

3、使用{{}}显示$scope中的变量

<p>{{hello.name}}</p>

 下面两种写法是等价的

<p>{{hello.name}}</p>
<p ng-bind="hello.name"></p>

 总结:留给我们的关键词是:module, module之间的协同和依赖, controller, 全局service依赖注入

 

项目目录

App/images // 存放Web前端使用的图片资源

App/Styles // 存放样式文件

App/scripts // 整个Web前端用到的脚本文件
                / Controllers // angularJS控制器模块存放目录
               /  directives // angularJs指令模块存放目录
              /   filters  // 过滤器模块存放目录
              /   services // 服务模块存放目录
            / app.js // Web前端程序配置模块(路由配置)
App/Modules  // 项目依赖库,angular、Bootstrap、Jquery库

App/Views // AngularJs视图模板存放目录

转载学习自:http://www.cnblogs.com/darrenji/p/4850739.html

written by ocean \\ tags:

5月 16

添加引用,这是引用的百度库

<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>

各版本最新地址

https://github.com/angular/angular.js/releases

AngularJS 通过 ng-directives 扩展了 HTML。

ng-app 指令定义一个 AngularJS 应用程序。

ng-model 指令把元素值(比如输入域的值)绑定到应用程序。

ng-bind 指令把应用程序数据绑定到 HTML 视图。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<body>
<div ng-app="">
 	<p>名字 : <input type="text" ng-model="name"></p>
 	<h1>Hello {{name}}</h1>
</div>
</body>
</html>

绑定条件的例子

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>angularjs 模板解释</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    <script type="text/javascript">
        (function () {
            var app = angular.module("testApp", []);
            app.controller("tmplController", ["$scope", function ($scope) {
                //给变量val赋值
                $scope.val = "学习AngularJS";
                //给变量list赋值
                $scope.list = [
                    { title: "古诗大全", url: "http://www.wx6.org/" },
                    { title: "成语大全", url: "http://chengyu.wx6.org/" },
                    { title: "词语大全", url: "http://ciyu.wx6.org/" },
                    { title: "汉字大全", url: "http://hanzi.wx6.org/" },
                    { title: "歇后语大全", url: "http://xiehouyu.wx6.org/" }
                ]
                //给变量hasValue赋值
                $scope.hasValue = false;
            }]);
        })()
    </script>
</head>
<body ng-app="testApp">
    <div ng-controller="tmplController">
        <!--普通输出-->
        <div>{{val}}</div>
        <!--循环-->
        <ul ng-repeat="item in list">
            <li><a href="{{item.url}}" rel=nofollow>{{item.title}}</a></li>
        </ul>
        <!--条件语句-->
        <div ng-if="!hasValue">
            Angularjs条件语句
        </div>
    </div>
</body>
</html>

&scope是控制器与页面沟通的主要元素,测试一下angularjs的双向绑定.

<!DOCTYPE html> 
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>angularjs控制器介绍</title>
        <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
        <script type="text/javascript">
            (function () {
                var app = angular.module("Yiim", []);
                app.controller("cntoController", ["$scope", function ($scope) {
                    var defaults = "ocean's test";
                    //设置值
                    $scope.val = defaults;
                    $scope.click = function () {
                        $scope.val = defaults;
                    };
                }]);
            })()
        </script>
    </head>
    <body ng-app="Yiim">
        <div ng-controller="cntoController">
            <!--绑定值-->
            <div><textarea ng-model="val"></textarea></div>
            <!--输出值-->
            <div>{{val}}</div>
            <!--绑定方法-->
            <div><button ng-click="click()">重置</button></div>
        </div>
    </body>
</html>


路由

单页Web应用由于没有后端URL资源定位的支持,需要自己实现URL资源定位。angularjs使用浏览器URL "#" 后的字符串来定位资源,区分不同的功能模块。

路由并非在angularjs核心文件内,需要另外加入一段脚本 “angular-route.min.js”

需要注意的是在创建 “app” 对象是需要填写对 ngRoute 依赖

route.html

<!DOCTYPE html>
<html ng-app="Yiim" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>angularjs路由介绍</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    <script src="http://apps.bdimg.com/libs/angular-route/1.3.13/angular-route.js"></script>
    <script type="text/javascript">
        (function () {
            //设置当前模块依赖,“ngRoute”,用.NET的理解就是给这个类库添加“ngRoute”引用
            var app = angular.module("Yiim", ['ngRoute']);
            //配置路由
            app.config(['$routeProvider', function ($routeProvider) {
                var route = $routeProvider;
                //指定URL为“/” 控制器:“indexController”,模板:“route.html”
                route.when('/list', { controller: 'listController', templateUrl: 'route-list.html' });
                //注意“/view/:id” 中的 “:id” 用于捕获参数ID
                route.when('/view/:id', { controller: 'viewController', templateUrl: 'route-view.html' });
                //跳转
                route.otherwise({ redirectTo: '/list' });
            }]);
            //创建一个提供数据的服务器
            app.factory("service", function () {
                var list = [
                    { id:1, title: "古诗大全", url: "http://www.wx6.org/" },
                    { id: 2, title: "成语大全", url: "http://chengyu.wx6.org/" },
                    { id: 3, title: "词语大全", url: "http://ciyu.wx6.org/" },
                    { id: 4, title: "汉字大全", url: "http://hanzi.wx6.org/" },
                    { id: 5, title: "歇后语大全", url: "http://xiehouyu.wx6.org/" }
                ];
                return function (id) {
                    //假如ID为无效值返回所有
                    if (!id) return list;
                    var t = 0;
                    //匹配返回的项目
                    angular.forEach(list, function (v, i) {
                        if (v.id == id) t = i;
                    });
                    return list[t];
                }
            })
            //创建控制器 indexController
            app.controller("listController", ["$scope", "service", function ($scope, service) {
                //获取所有数据
                $scope.list = service();
            }]);
            //创建查看控制器 viewController, 注意应为需要获取URL ID参数 我们多设置了一个 依赖注入参数 “$routeParams” 通过它获取传入的 ID参数
            app.controller("viewController",
                            ["$scope", "service", '$routeParams',
                                function ($scope, service, $routeParams) {
                                    $scope.model = service($routeParams.id || 0) || {};
                                }
                            ]
                            )
        })()
    </script>
</head>
<body>
    <div><a href="#/list">列表</a></div>
    <div ng-view>
    </div>
</body>
</html>

route-list.html

<ul ng-repeat="item in list">
    <li><a href="#view/{{item.id}}">{{item.title}}</a></li>
</ul>

route-view.html

<div>
    <div>网站ID:{{model.id}}</div>
    <div>网站名称:<a href="{{model.url}}" rel="nofollow">{{model.title}}</a></div>
    <div>访问地址:{{model.url}}</div>
</div>

以上代码中,我们首先配置了三条个处理个局部页面的路由

路由处理列表页并设置控制器为"listController",指定模板页为"route-list.html"

route.when('/list', { controller: 'listController', templateUrl: 'route-list.html' });

 

与上面不同的是第二条路由中包含":id"用于捕获URL后面的参数 。

route.when('/view/:id', { controller: 'viewController', templateUrl: 'route-view.html' });

 

处理所有未匹配到的路由跳转到 "'/list'"内。

route.otherwise({ redirectTo: '/list' });

 

我们还使用了模块方法 "factory" 创建一个"service" 服务,用于获取数据列表

后面我们声明了两个控制器"listController","viewController",同时配置对"service"的依赖,"viewController" 中我们还添加对"$routeParams" 的依赖,用于获取路由捕获的id。

需要注意的是我们再主页面声明了"ng-view"用于指定局部页面和控制器作用范围。

<div ng-view></div>

 

指令

 

下面的例子中,我们使用模块创建了一个指令"imCheck",并在指令方法"link"注册了使用当前指令的dom对象注册了两个delegate方法 处理全选和子选择项状态改变处理的方法。

"imCheck" 对应在html页面的属性为 "im-check" 注意大小写。

<table ng-controller="dectController" im-check>

还要注意的是我们使用了jQuery来操作dom节点。

<!DOCTYPE html>
<html ng-app="Yiim" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>angularjs指令演示</title>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
    <script type="text/javascript">
        (function () {
            var app = angular.module("Yiim", []);

            //创建一个提供数据的服务器
            app.factory("service", function () {
                var list = [
                    { id: 1, title: "古诗大全", url: "http://www.wx6.org/" },
                    { id: 2, title: "成语大全", url: "http://chengyu.wx6.org/" },
                    { id: 3, title: "词语大全", url: "http://ciyu.wx6.org/" },
                    { id: 4, title: "汉字大全", url: "http://hanzi.wx6.org/" },
                    { id: 5, title: "歇后语大全", url: "http://xiehouyu.wx6.org/" }
                ];
                return function (id) {
                    //假如ID为无效值返回所有
                    if (!id) return list;
                    var t = 0;
                    //匹配返回的项目
                    angular.forEach(list, function (v, i) {
                        if (v.id == id) t = i;
                    });
                    return list[t];
                }
            })
            //创建指令imCheck 在HTML中的语法为 im-check
            app.directive("imCheck", [function () {
                return {
                    restrict: 'A',
                    replace: false,
                    link: function (scope, element) {
                        var all = "thead input[type='checkbox']";
                        var item = "tbody input[type='checkbox']";
                        //当点击选择所有事便利所有项目
                        element.on("change", all, function () {
                            var o = $(this).prop("checked");
                            var tds = element.find(item);
                            tds.each(function (i, check) {
                                $(check).prop("checked", o);
                            });
                        });
                        //子项修改时的超值
                        element.on("change", item, function () {
                            var o = $(this).prop("checked");
                            var isChecked = true;
                            if (o) {
                                element.find(item).each(function () {
                                    if (!$(this).prop("checked")) {
                                        isChecked = false;
                                        return false;
                                    }
                                    return true;
                                });
                            }
                            element.find(all).prop("checked", o && isChecked);
                        });
                    }
                };
            }])

            app.controller("dectController", ['$scope', 'service', function ($scope, service) {
                $scope.list = service();
            }])
        })();
    </script>
</head>
<body>
    <!--注意一下标签 im-check 指定使用的指令-->
    <table ng-controller="dectController" im-check>
        <thead>
            <tr>
                <th><input type="checkbox">选择</th>
                <th>网站ID</th>
                <th>网站名称</th>
                <th>链接地址</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="item in list">
                <td><input type="checkbox"></td>
                <td>{{item.id}}</td>
                <td>{{item.title}}</td>
                <td>{{item.url}}</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

 

过滤器

 

angularjs过滤器,用来格式化数据(转化,排序,筛选等操作)。

<!DOCTYPE html>
<html ng-app="Yiim" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>angularjs 过滤器</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
    <script type="text/javascript">
        (function () {
            var app = angular.module("Yiim", []);
            app.controller("namesController", ["$scope", function ($scope) {
                $scope.names = [
                     { "Name": "Alfreds Futterkiste", "City": "Berlin", "Country": "Germany" },
                     { "Name": "Berglunds snabbköp", "City": "Luleå", "Country": "Sweden" },
                     { "Name": "Centro comercial Moctezuma", "City": "México D.F.", "Country": "Mexico" },
                     { "Name": "Ernst Handel", "City": "Graz", "Country": "Austria" },
                     { "Name": "FISSA Fabrica Inter. Salchichas S.A.", "City": "Madrid", "Country": "Spain" },
                     { "Name": "Galería del gastrónomo", "City": "Barcelona", "Country": "Spain" },
                     { "Name": "Island Trading", "City": "Cowes", "Country": "UK" },
                     { "Name": "Königlich Essen", "City": "Brandenburg", "Country": "Germany" },
                     { "Name": "Laughing Bacchus Wine Cellars", "City": "Vancouver", "Country": "Canada" },
                     { "Name": "Magazzini Alimentari Riuniti", "City": "Bergamo", "Country": "Italy" },
                     { "Name": "North/South", "City": "London", "Country": "UK" },
                     { "Name": "Paris spécialités", "City": "Paris", "Country": "France" },
                     { "Name": "Rattlesnake Canyon Grocery", "City": "Albuquerque", "Country": "USA" },
                     { "Name": "Simons bistro", "City": "København", "Country": "Denmark" },
                     { "Name": "The Big Cheese", "City": "Portland", "Country": "USA" },
                     { "Name": "Vaffeljernet", "City": "Århus", "Country": "Denmark" },
                     { "Name": "Wolski Zajazd", "City": "Warszawa", "Country": "Poland" }
                ];
            }])
        })()
    </script>
</head>
<body>
    <div ng-controller="namesController">
        <p>输入过滤:</p>
        <p><input type="text" ng-model="name"></p>
        <ul>
            <li ng-repeat="x in names | filter:name | orderBy:'Country'">
                {{ (x.Name | uppercase) + ', ' + x.country }}
            </li>
        </ul>
    </div>
</body>
</html>

written by ocean

12月 06

内容里有两个ifame 

<iframe id="leftiframe"…</iframe> 

<iframe id="mainiframe..</iframe> 

leftiframe中jQuery改变mainiframe的src代码: 

$("#mainframe",parent.document.body).attr("src","http://www.jb51.net ") 

 如果内容里面有一个ID为mainiframe的ifame 

<iframe id="mainifame"…></ifame> 

ifame包含一个someID 

<div id="someID">you want to get this content</div> 

得到someID的内容 

$("#mainiframe").contents().find("someID").html() html 或者 $("#mainiframe").contains().find("someID").text()值 

如上面所示 

leftiframe中的jQuery操作mainiframe的内容someID的内容 

$("#mainframe",parent.document.body).contents().find("someID").html()或者 $("#mainframe",parent.document.body).contents().find("someID").val() 

 

在父窗口中操作 选中IFRAME中的所有单选钮

$(window.frames["iframe1"].document).find("input[ at type='radio']").attr("checked","true");

在IFRAME中操作 选中父窗口中的所有单选钮

$(window.parent.document).find("input[ at type='radio']").attr("checked","true");

iframe框架的:<iframe src="test.html" id="iframe1" width="700" height="300" frameborder="0" scrolling="auto"></iframe>

IE7中测试通过

在父页面访问Iframe子窗体的txtAddress控件 

window.frames["ifrMapCompanyDetails"].document.all("txtAddress").value = '地址' ; 

   

在Iframe子窗体1访问父页面的TextBox1控件 , 子窗体1把值赋给子窗体2的某个控件 

string strValue = "从子窗体传递给父页面的值" ; 

下面是在Page_Load事件里面调用的,当然可以写在javascript脚本里面 

this.Response.Write("<script>parent.document.all('TextBox1').value = '" + strValue + "';</script>"); 

this.Response.Write("<script>if( parent.document.all('TextBox2').value = '0')parent.document.all('TextBox1').value = '44';</script>"); 

子窗体访问父窗体中的全局变量: 

parent.xxx; 

在Iframe子窗体1访问子窗体2的txtAddress控件 子窗体1把值赋给子窗体2的某个控件 

window.parent.frames["ifrMapCompanyDetails"].document.all("txtAddress").value = '地址' ; 

父窗体提交两个Iframe子窗体 

window.frames["ifrMapCompanyDetails"].Form1.submit(); 

window.frames["ifrMapProductInfoDetails"].Form1.submit(); 

Iframe子窗体 调用父页面的javascript事件 

window.parent.XXX() 

//父页面调用当前页面中IFRAME子页面中的脚本childEvent 

function invokechildEvent() 

{ var frm = document.frames["ifrChild1"].childEvent(); } 

或者调用当前页面中第一个IFRAME中的脚本childEvent 

{ var frm = document.frames[0]; frm.childEvent(); } 

//子页面调用父窗体的某个按钮的按钮事件 

window.parent.Form1.btnParent.click() 

父页面调用子窗体的某个按钮的按钮事件 

window.frames['ifrChild1'].document.all.item("btnChild3").click(); 

//jquery 部分: 

在父窗口中操作 选中IFRAME中的所有单选钮 

$(window.frames["iframe1"].document).find("input[ at type='radio']").attr("checked","true"); 

在IFRAME中操作 选中父窗口中的所有单选钮 

$(window.parent.document).find("input[ at type='radio']").attr("checked","true");

written by ocean

9月 18

做了个Bootstrap的小项目,实在不能忍受浏览器自带alert的丑陋,于是找了个漂亮的弹框插件.

Bootbox.js 是一个小型的 JavaScript 库用来创建简单的可编程对话框,基于 Twitter 的 Bootstrap 开发。

 

官方下载地址

https://github.com/makeusabrew/bootbox

 

bootbox.js使用三方法设计模仿他们的本地JavaScript一些方法。

bootbox.alert(message, callback)
bootbox.prompt(message, callback)
bootbox.confirm(message, callback)

Alert

        bootbox.alert("http://blog.wx6.org", function () {
            //todo
        });

Confirm

        bootbox.confirm("http://blog.wx6.org", function (result) {
            //todo
        });

Prompt

        bootbox.prompt("http://blog.wx6.org", function (result) {
            if (result === null) {
                //todo
            } else {
                //todo
            }
        });

最复杂的Dialog,我是内签了一个iframe

           bootbox.dialog({  
               message: "<iframe id='ifr' width=100% height=600px frameborder=0 src='SelectImgFromWeiXinMessage.aspx' scrolling=false ></iframe>",  
               title: "选择图片",   
               buttons: {  
                   Cancel: {  
                       label: "Cancel",  
                       className: "btn-default",  
                       callback: function () {  
                       }  
                   }  
                   , OK: {  
                       label: "OK",  
                       className: "btn-primary",  
                       callback: function () {  
                          //debugger;
                          //var src= window.frames["ifr"].document.getElementById("imgsrc").value;
                          //alert(src); 
                       }  
                   }  
               } 
           });

当然它还可以用div等方式

附上dialog的API

bootbox.dialog({
  // dialog的内容
  message: "I am a custom dialog",
   
  // dialog的标题
  title: "Custom title",
   
  // 退出dialog时的回调函数,包括用户使用ESC键及点击关闭
  onEscape: function() {},
   
  // 是否显示此dialog,默认true
  show: true,
   
  // 是否显示body的遮罩,默认true
  backdrop: true,
   
  // 是否显示关闭按钮,默认true
  closeButton: true,
   
  // 是否动画弹出dialog,IE10以下版本不支持
  animate: true,
   
  // dialog的类名
  className: "my-modal",
   
  // dialog底端按钮配置
  buttons: {
     
    // 其中一个按钮配置
    success: {   
      // 按钮显示的名称
      label: "Success!",
       
      // 按钮的类名
      className: "btn-success",
       
      // 点击按钮时的回调函数
      callback: function() {}
    },
     
    // 另一个按钮配置
    "Danger!": {
      className: "btn-danger",
      callback: function() {}
    }
  }
});

written by ocean

4月 22

<script>
       $(function () {
           $("#photo").click(function (event) {
               alert(event.pageX+"—"+ event.pageY);
           });
       });
   </script>

written by ocean

3月 12

一、变量的作用域

要理解闭包,首先必须理解Javascript特殊的变量作用域。

变量的作用域无非就是两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

Js代码

  var n=999;
  function f1(){
    alert(n);
  }
  f1(); // 999

另一方面,在函数外部自然无法读取函数内的局部变量。

Js代码

  function f1(){
    var n=999;
  }
  alert(n); // error

这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

Js代码

  function f1(){
    n=999;
  }
  f1(); //如果此处不调用f1(),也报错
  alert(n); // 999

——————————————————————————————————–

二、如何从外部读取局部变量?

出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。

那就是在函数的内部,再定义一个函数。

Js代码

  function f1(){
    n=999;
    function f2(){
      alert(n); // 999
    }
  }

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1 就是不可见的。这就是Javascript语言特有的“链式作用域”结构(chain scope)

子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

       function f1() {
           function f2() {
               alert(n);
           }
           var n = 999;
           return f2;
       }
       var result = f1();
       result(); //此处OK,因为n是定义在f1里面的,不管顺序,f2都可以找到
       alert(n);  //此处会报错,因为n是局部变量

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

Js代码

  function f1(){
    n=999;
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999

——————————————————————————————————–

三、闭包的概念

上一节代码中的f2函数,就是闭包。

各种专业文献上的“闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

——————————————————————————————————–b

四、闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

怎么来理解这句话呢?请看下面的代码。

Js代码

  function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000

在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个

匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

——————————————————————————————————–

五、使用闭包的注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便

改变父函数内部变量的值。

——————————————————————————————————–

六、思考题

如果你能理解下面代码的运行结果,应该就算理解闭包的运行机制了。

Js代码

  var name = "The Window"; 
  var object = { 
    name : "My Object", 
    getNameFunc : function(){ 
      return function(){ 
        return this.name; 
     }; 
    } 
     }; 
    alert(object.getNameFunc()()); //The Window

——————————————————————————————————–
JavaScript闭包例子

function outerFun()
{
var a=0;
function innerFun()
{
a++;
alert(a);
} 
}
innerFun()

上面的代码是错误的.innerFun()的作用域在outerFun()内部,所在outerFun()外部调用它是错误的.

改成如下,也就是闭包:

Js代码

function outerFun()
{
var a=0;
function innerFun()
{
a++;
alert(a);
}
return innerFun; //注意这里
}
var obj=outerFun();
obj(); //结果为1
obj(); //结果为2
var obj2=outerFun();
obj2(); //结果为1
obj2(); //结果为2

什么是闭包:

当内部函数 在定义它的作用域 的外部 被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们.

——————————————————————————————————–

再来看一个例子

Js代码

function outerFun()
{
var a =0;
alert(a);
}
var a=4;
outerFun();
alert(a);

结果是 0,4 . 因为在函数内部使用了var关键字 维护a的作用域在outFun()内部.

再看下面的代码:

Js代码

       function outerFun() {

           a = 0; //没有var

           alert(a);

       }

       var a = 4;

       outerFun();

       alert(a);

结果为 0,0 真是奇怪,为什么呢?

作用域链是描述一种路径的术语,沿着该路径可以确定变量的值 .当执行a=0时,因为没有使用var关键字,因此赋值操作会沿着作用域链到var a=4; 并改变其值.


最后再补充两种

       function outerFun() {

           alert(a);

           a = 0;

       }

       a = 4;

       outerFun();

       alert(a);

答案是  4,0  

       function outerFun() {

           alert(a);

           var a = 0;

       }

       a = 4;

       outerFun();

       alert(a);

答案是 undifined,4

详细出处参考:http://www.jb51.net/article/24101.htm

written by ocean

2月 17

       <script>
           function Import(path, type, title) {
               var s, i;
               if (!type) type = path.substr(path.lastIndexOf(".") + 1);
               if (type == "js") {
                   var ss = document.getElementsByTagName("script");
                   for (i = 0; i < ss.length; i++) {
                       if (ss[i].src && ss[i].src.indexOf(path) != -1 || ss[i].title == title) return ss[i];
                   }
                   s = document.createElement("script");
                   s.type = "text/javascript";
                   s.src = path;
                   if (title) s.title = title;
               }
               else if (type == "css") {
                   var ls = document.getElementsByTagName("link");
                   for (i = 0; i < ls.length; i++) {
                       if (ls[i].href && ls[i].href.indexOf(path) != -1 || ls[i].title == title) return ls[i];
                   }
                   s = document.createElement("link");
                   s.rel = "stylesheet";
                   s.type = "text/css";
                   s.href = path;
                   if (title) s.title = title;
                   s.disabled = false;
               }
               else return;
               var head = document.getElementsByTagName("head")[0];
               head.appendChild(s);
               return s;
           }

           var xx = Import("1.js", "js");
      </script>
       <script>
           Test();
       </script>

网上淘到这么一个函数,挺好用的

注意关键地方

written by ocean

11月 26

在 javascript 中,可以使用 == 来比较两个数据是否相等,如果两个数据的类型不同,那么,将在进行转换后进行比较,转换的规则如下:

    如果其中一个操作数的类型为 Boolean ,那么,首先将它转换为数字类型,false 转换为 0, true 将转换为 1。

    如果其中一个操作数的类型是字符串,另外一个为数字类型,那么,将字符串转换为数字进行比较。

    如果其中一个操作数的类型是字符串,另外一个为 object 类型,那么,将调用对象的 toString 方法之后,比较字符串。

    如果其中一个操作数的类型是数字类型,另外一个为 object 类型,那么,将对象转换为数值后进行数字比较。

以下的规定了一些特殊的比较:

    null 和 undefined 是相等的。

    null 和 undefined 不会转换为任何其他类型

    如果任何一个操作的结果为 NaN,那么相等比较返回 false,不相等比较返回 true。注意,即使两个操作数都为 NaN,返回结果一样是 false,也就是说,NaN 不等于 NaN。

    如果两个操作数都是对象,那么比较它们引用的值,如果引用同一个对象,那么,返回真,否则,返回假。

alert(null == undefined);    // true

alert(undefined == null);    // true

alert(true == 1);    // true

alert(false == 0); // true

alert(true == 2);    // false

var obj = {};    

alert(10 == obj);    // false

完全相同的比较 === 和不完全相等 !==

完全相同的比较用来比较不进行转换是否相等,例如:

var a = "100";

var b = 100;

alert(a == b);       // true

alert(a === b);      // false

== 比较将返回真,因为 “100” 首先转换为数字 100, 然后与数字 100 进行比较,结果相等。

=== 比较将返回假,因为字符串 ”100” 不经过转换的话,与数字 100 不相等。

!== 用于比较在不转换的情况下,是否不相等。

alert(a != b);       // false

alert(a !== b);      // true

第一种情况将返回假,因为转换后是相等的。第二种情况将返回真,因为不经过转换的话,他们一个是字符串,一个是数字,是不相等的。

转帖地址:http://www.cnblogs.com/haogj/archive/2010/04/24/1719522.html

written by ocean