• javascript高级程序设计笔记-第七章(函数表达式)


    一、递归

    递归函数是在一个函数通过名字调用自身的情况下构成的

    function factorial(num) {
    	if (num <= 1) {
    		return 1;
    	} else {
    		return num * factorial(num-1);
    	}
    }
    

    但是将此函数赋值给另一个函数时会出错

    var anotherFactorial = factorial;
    factorial = null;
    alert(anotherFactorial(4));		//报错
    

    使用arguments.callee

    function factorial(num) {
    	if (num <= 1) {
    		return 1;
    	} else {
    		return num * arguments.callee(num-1);
    	}
    }
    var anotherFactorial = factorial;
    factorial = null;
    alert(anotherFactorial(4));		//24
    

    但是arguments.callee在严格模式下会导致错误
    所以严格模式下,使用命名函数表达式

    var factorial = (function f(num) {
    	if (num <= 1) {
    		return 1;
    	} else {
    		return num * f(num-1);
    	}
    });
    //创建一个名为f()的命名函数表达式,然后将其赋值给变量factorial
    

    二、闭包

    闭包是有权访问另一个函数作用域中的变量的函数,通常是通过在一个函数内部创建另一个函数来创建闭包

    function compare(value1, value2) {
    	if (value1 < value2) {
    		return -1;
    	} else if (value1 > value2) {
    		return 1;
    	} else {
    		return 0;
    	}
    }
    var result = compare(5, 10);
    

    下图是compare()函数执行时的作用域链

    一般当函数执行完毕后,局部活动对象就会被销毁,但是闭包不是,当creatComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但是它的活动对象仍然会留在内存中;直到匿名函数被销毁后,它的活动对象才会被销毁

    function creatComparisonFunction(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 = creatComparisonFunction("name");
    //调用函数
    var result = compareNames({name: "Nicholas"}, {name: "Greg"});
    

    1、闭包与变量

    副作用:闭包只能取得包含函数中任何变量的最后一个值

    function createFunctions() {
    	var result = new Array();
    	for (var i = 0; i < 10; i++) {
    		result[i] = function() {
    			return i;
    		};
    	}
    	return result;
    }
    

    这个函数会返回一个数组,表面上看,似乎每个函数都应该返回自己的索引值,实际上每个函数都返回10

    可以定义一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。而在这个匿名函数内部,创建一个闭包

    function createFunctions() {
    	var result = new Array();
    	for (var i = 0; i < 10; i++) {
    		result[i] = function(num) {
    			return function() {
    				return num;
    			};
    		}(i);
    	}
    	return result;
    }
    

    2、关于this对象

    在全局函数中,this等于window,当函数被作为某个对象的方法调用时,this等于那个对象。
    匿名函数的执行环境具有全局性,其this通常指向window。

    var name = "the window";
    var object = {
    	name: "my object",
    	getNameFunc: function() {
    		return function() {
    			return this.name;
    		};
    	}
    };
    alert(object.getNameFunc()());		//the window
    

    把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象

    var name = "the window";
    var object = {
    	name: "my object",
    	getNameFunc: function() {
    		var that = this;
    		return function() {
    			return that.name;
    		};
    	}
    };
    alert(object.getNameFunc()());		//my object
    

    三、模仿块级作用域(私有作用域)

    (function() {
    	//这里是块级作用域
    })();
    

    将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式,紧随其后的另一对圆括号会立即调用这个函数

    function() {
    	//这里是块级作用域
    }();	//报错
    //函数声明后面不能跟圆括号,而函数表达式后面可以跟圆括号
    

    如果只是临时需要一些变量,就可以使用私有作用域

    function outputNumbers() {
    	(function() {
    		for (var i = 0; i < 10; i++) {
    			console.log(i);		//0,1,2,3,4,5,6,7,8,9
    		}
    	})();
    	console.log(i);		//报错
    }
    outputNumbers();
    

    这种技术通常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数

    四、私有变量

    任何在函数中定义的变量,都可以认为是私有变量。私有变量包括函数的参数、局部变量和函数内部定义的其他函数

    特权方法:有权访问私有变量和私有函数的共有方法

    方法是在构造函数中定义特权方法

    function MyObject() {
    	var privateVariable = 10;
    	function privateFunction() {
    		return false;
    	}
    	//特权方法
    	this.publicMethod = function() {
    		privateVariable ++;
    		return privateFunction();
    	};
    }
    //变量privateVariable和函数privateFunction()只能通过特权方法publicMethod()来访问
    

    可以利用私有和特权成员,隐藏那些不应该被直接修改的数据

    function Person(name) {
    	this.getName = function() {
    		return name;
    	};
    	this.setName = function(value) {
    		name = value;
    	};
    }
    var person = new Person("Nicholas");
    alert(person.getName());		//Nicholas
    person.setName("Greg");
    alert(person.getName());		//Greg
    

    1、静态私有变量

    (function MyObject() {
    	//私有变量和私有函数
    	var privateVariable = 10;
    	function privateFunction() {
    		return false;
    	}
    	//构造函数
    	MyObject = function() {};
    	//特权方法
    	MyObject.prototype.publicMethod = function() {
    		privateVariable ++;
    		return privateFunction();
    	};
    })();
    

    2、模块模式

    为单例创建私有变量和特权方法,单例指只有一个实例的对象

    var singleton = function() {
    	//私有变量和函数
    	var var privateVariable = 10;
    	function privateFunction() {
    		return false;
    	}
    	//特权方法和属性
    	return {
    		publicProperty: true,
    		publicMethod: function() {
    			privateVariable ++;
    			return privateFunction();
    		}
    	};
    }();
    

    如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有数据的方法,就可以使用模块模式

    3、增强的模块模式

    适合那些单例必须是某种类型的实例,同时还必须添加某些属性和方法对其加以增强的情况

    var singleton = function() {
    	//私有变量和函数
    	var var privateVariable = 10;
    	function privateFunction() {
    		return false;
    	}
    	//创建对象
    	var object = new CustomType();
    	//添加特权方法和属性
    	object.publicProperty = true;
    	object.publicMethod = function() {
    		privateVariable ++;
    		return privateFunction();
    	};
    	//返回这个对象
    	return object;
    }();
  • 相关阅读:
    leetcode 10 正则表达式匹配(c++)
    基于.NetCore3.1系列 —— 日志记录之初识Serilog
    AspNetCore WebApi:Serilog(日志)
    .NET Core下的日志(3):如何将日志消息输出到控制台上
    Asp.Net Core用NLog记录日志操作方法
    .NET Core3.0 日志 logging-最好用的日志集合介绍
    .net core 3.1 使用nlog记录日志 NLog.Web.AspNetCore
    NetCore3.1 日志组件 Nlog的使用
    配置 ASP.NET Core 请求(Request)处理管道
    vue进入页面每次都调用methods里的方法
  • 原文地址:https://www.cnblogs.com/u14e/p/5235713.html
Copyright © 2020-2023  润新知