js——函数表达式

来源:互联网 发布:淘宝卖家账号多少钱 编辑:程序博客网 时间:2024/04/30 20:39
<span style="font-size:18px;">function createComparisonFunction(propertyName) {return function (object1, object2) {var value1 = object1[propertyName];var value2 = object2[propertyName];if (value1 < value2) {return -1;} else if (value1 > value2) {return 1;} else {return 0;}};}//创建函数var compareNames = createComparisonFunction("name"); //调用函数var result = compareNames({ name: "Nicholas" }, { name: "Greg" }); //解除对匿名函数的引用(以便释放内存)compareNames = null;</span>

作用域


<span style="font-size:18px;">// 一、定义函数的方式// 1、函数声明// 函数声明,它有重要特征就是函数声明提升(function declaration hoisting),// 即在执行代码之前会先读取函数声明。这就意味着可以把函数声明放在调用它的语句后面。function funcName(arg1, arg2) {}console.info(funcName.name);// 2、函数表达式// 这种情况下创建的函数叫做匿名函数(anonymous function),匿名函数有时候也叫拉姆达函数。var funcName = function(arg1, arg2) {};var sayWords;var condition = false;if (condition) {sayWords = function() {console.info("hello");}} else {sayWords = function() {console.info("world");}}// 二、将函数作为其他函数的值返回function createComparisonFunction(propertyName) {return function (object1, object2) {var value1 = object1[propertyName];var value2 = object2[propertyName];if (value1 < value2) {return -1;} else if (value1 > value2) {return 1;} else {return 0;}};}var people = [];for (var i = 0; i < 5; i++) {var person = new Object();person.age = (i-2) * (i-2) - 3;person.name = "Jack";people.push(person);}people.sort(createComparisonFunction("age"));console.info(people);// 三、递归function factorial(num) {if (num <= 1) {return 1;} else {return num * factorial(num - 1);}}console.info("factorial(5):" + factorial(5));var anotherFactorial = factorial; factorial = null; alert(anotherFactorial(4)); // 出错// arguments.callee 是一个指向正在执行的函数的指针// 在严格模式下,不能通过脚本访问arguments.calleefunction factorial(num) {if (num <= 1) {return 1;} else {return num * arguments.callee(num - 1);}}// 使用命名函数表达式var factorial = (function f(num) {if (num <= 1) {return 1;} else {return num * f(num - 1);}});// 四、闭包// 闭包是指有权访问另一个函数作用域中的变量的函数。// 由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。// 4.1、闭包与变量function createFuncs() {varresult = new Array();for (var i = 0; i < 10; i++) {result[i] = function() {return i;};}return result;}// 闭包副作用,即闭包只能取得包含函数中任何变量的最后一个值。var funcs = createFuncs();for (var i = 0; i < funcs.length; i++) {console.info(funcs[i]());}function createFuncs1(){ var result = new Array(); for (var i=0; i < 10; i++) { result[i] = function(num) { return function() {  return num; }; }(i);} return result; } var funcs = createFuncs1();for (var i = 0; i < funcs.length; i++) {console.info(typeof funcs[i]);console.info(funcs[i]());}// 4.2 this对象// this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,// 而当函数被作为某个对象的方法调用时,this等于那个对象。// 不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window。// 每个函数在被调用时都会自动取得两个特殊变量:this和arguments。// 内部函数在搜索这两个变量时,只会搜索到其活动对象为止,// 因此永远不可能直接访问外部函数中的这两个变量。var name = "The Window"; var object = { name: "My Object", getNameFunc: function(){ return function(){ return this.name; }; } }; console.info(object.getNameFunc()()); // "The Window"(在非严格模式下)var object = {name: "My object",getNameFunc: function() {var that = this;return function() {return that.name;}}}console.info(object.getNameFunc()()); // "My Object"// 4.3 内存泄露function assignHandler(){ var element = document.getElementById("someElement"); element.onclick = function() { alert(element.id); }; }function assignHandler(){ var element = document.getElementById("someElement"); var id = element.id; element.onclick = function(){ alert(id); }; element = null; } // 五、模仿块级作用域function outputNumbers(array, count) {for (var i = 0; i < count; i++) {console.info(array[i]);}console.info("i = ", i); // i = 5}var arr = [1, 4, 6, 3, 7];outputNumbers(arr, arr.length);function outputNumbers1(array, count) {for (var i = 0; i < count; i++) {console.info(array[i]);}var i; // 忽视该声明console.info("i = ", i); // i = 5}outputNumbers1(arr, arr.length);// JavaScript 没有块级作用域的概念,匿名函数可以用来模仿块级作用域。(function(){ // 这里是块级作用域})(); function outputNumbers(array, count) { (function () { for (var i = 0; i < count; i++) { console.info(array[i]); } })(); console.info("i = ", i); //导致一个错误!} (function() { var now = new Date(); if (now.getMonth() == 0 && now.getDate() == 1) { console.info("Happy new year!"); } })(); // 六、私有变量// JavaScript中没有私有成员的概念;所有对象属性都是公有的。但有私有变量的概念。// 任何在函数中定义的变量,都可以认为是私有变量。// 私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。// 权访问私有变量和私有函数的公有方法称为特权方法(privileged method)。// 利用闭包的作用域// 1、实例变量function MyObject() { // 私有变量和私有函数var privateVariable = 10; function privateFunction() { return false; } // 特权方法this.publicMethod = function () { privateVariable++; return privateFunction(); }; } function Person(name){ this.getName = function(){ return name; }; this.setName = function (value) { name = value; }; } var person = new Person("hello"); console.info(person.getName()); // "hello" person.setName("world"); console.info(person.getName()); // "world" // 2、静态私有变量(function(){ // 私有变量和私有函数var privateVariable = 10; function privateFunction(){ return false; } // 构造函数MyObject = function(){ }; // 公有/特权方法MyObject.prototype.publicMethod = function(){ privateVariable++; return privateFunction(); }; })();(function(){ var name = ""; Person = function(value){ name = value; }; Person.prototype.getName = function(){ return name; }; Person.prototype.setName = function (value){ name = value; }; })(); var person1 = new Person("All"); console.info(person1.getName()); //"All" person1.setName("is"); console.info(person1.getName()); //"is" var person2 = new Person("well"); console.info(person1.getName()); //"well" console.info(person2.getName()); //"well" // 3、模块模式// 通常JavaScript是以对象字面量的方式来创建单例对象的var singleton = { name : value, method : function () { //这里是方法的代码} }; // 模块模式通过为单例添加私有变量和特权方法能够使其得到增强。// 如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有// 数据的方法,那么就可以使用模块模式。var singleton = function() { // 私有变量和私有函数var privateVariable = 10; function privateFunction() {  return false; } //特权/公有方法和属性return { publicProperty: true, publicMethod : function() { privateVariable++; return privateFunction(); } }; }(); var application = function() { //私有变量和函数var components = new Array(); //初始化components.push(new BaseComponent()); //公共return { getComponentCount : function() { return components.length;     }, registerComponent : function(component) { if (typeof component == "object") { components.push(component); } } }; }(); 1、增强的模块类型// 对某种类型的实例进行加强var singleton = function(){ //私有变量和私有函数var privateVariable = 10; function privateFunction(){ return false; } //创建对象var object = new CustomType(); //添加特权/公有属性和方法object.publicProperty = true; object.publicMethod = function(){ privateVariable++; return privateFunction(); }; //返回这个对象return object; }(); var application = function(){ //私有变量和函数var components = new Array(); //初始化components.push(new BaseComponent()); //创建application的一个局部副本var app = new BaseComponent(); //公共接口app.getComponentCount = function() { return components.length; }; app.registerComponent = function(component) { if (typeof component == "object") { components.push(component); } }; //返回这个副本return app; }(); //有点像C#泛型中对类型参数的约束internal class Base { public virtual void M<T1, T2>() where T1 : struct where T2 : class { } }</span>
总结
1、当在函数内部定义了其他函数时,就创建了闭包。闭包有权访问包含函数内部的所有变量。
(在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域。
2、闭包可以在JavaScript中模仿块级作用域
创建并立即调用一个函数,这样既可以执行其中的代码,又不会在内存中留下对该函数的引用。
3、闭包可以用于在对象中创建私有变量
即使JavaScript中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公有方法可以访问在包含作用域中定义的变量。有权访问私有变量的公有方法叫做特权方法(privileged method)
内容主要摘自《JavaScript高级程序设计》

0 0
原创粉丝点击