JavaScript 函数

JS的函数是参数化的。

如果函数挂载在一个对象上,作为对象的一个属性,就称它为对象的方法。当通过这个对象来调用函数的方法。当通过这个对象来调用函数时,该对象就是此次上下文,也就是this的值。用于初始化一个新建对象的函数称为构造函数。

 

函数调用

作为函数

作为方法

作为构造函数

通过它们的call()和apply()方法间接调用

 

方法调用

如果有一个函数f和一个对象o,可以用以下的代码给o定义一个方法m:

//给o定义m()
o.m = f;

//调用m
o.m();
o.m(x,y)

方法调用和函数调用有一个重要的区别:调用上下文:

 

	var calculator = {//对象直接量
		operand1: 1,
		operand2: 1,
		
		add:function(){
			this.result = this.operand1 + this.operand2;
		}
		
	};
	calculator.add();
	calculator.result; // => 2

如果想访问外部函数的this值 ,需要将this的值保存在一个变量里,这个变量和内部函数都同在一个作用域内,通用常用self来保存this

	var o = {//对象o
		m:function(){//对象里的方法m()
			var self = this; //将this的值保存至一个变量中
			console.log(this === o); //true
			f(); //调用函数f()
			function f(){
				console.log(this === o); //false  this的值是全局对象或undefined
				console.log(self === o); // true  self指外部函数的this值
			}
		}
	}
	o.m();

构造函数的调用

如果函数或者方法之前带有关键字new,它就构成构造函数调用。

var o = new Object();
var o = new Object;

//上下等价

 

间接调用

call(),apply()

这两个方法都允许显式指定调用所需的this值。也就是说,任何函数都可以作为任何对象的方法来调用,哪怕这个函数不是那个对象的方法。

 

作为值的函数

函数可以定义,也可以调用。

function square(x){ return x*x };

var s = square;
square (4); // 16
s (4); // 16
	function add(x,y) {
		return x+y;
	}
	function subtrach(x,y) {
		return x - y;
	}
	function multiply(x,y) {
		return x*y;
	}
	function divide(x,y) {
		return x/y;
	}
	
	function operate (operator,operand1,operand2) {
		return operator ( operand1,operand2);
	}
	var i = operate(add,operate(add,2,3),operate(multiply,4,5)) //25

 

作为命名空间的函数

function mymodule () {
	//模块代码
	//这个模块所使用的所有变量都是局部变量
	//而不是污染命名空间
	
}
mymodule(); //不要忘了还要调用这个函数

//也可以定义为匿名函数

(function () {
	//mymodule() 函数重写为匿名的函数表达式
	//模块代码
}());//结束函数定义并立即调用它

 

 

闭包

1、概念
闭包函数:声明在一个函数中的函数,叫做闭包函数。

闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量

2、特点


  
  让外部访问函数内部变量成为可能;

  局部变量会常驻在内存中;

  可以避免使用全局变量,防止全局变量污染;

 

理解闭包要了解嵌套函数的词法作用域规则:

var scope = "global scope";//全局变量
	function checkscope() {
		var scope = 'local scope'; //局部变量
		function f() {
			return scope; //在作用域中返回这个值
		}
		return f();
	}
	checkscope(); //"local scope"
	function funA(){
	  var a = 10;  // funA的活动对象之中;
	  return function(){   //匿名函数的活动对象;
	        alert(a);
	  }
	}
	var b = funA();
	b();// 10

 

	var uniqueInteger = (function() {
		//函数定义并立即调用
		var counter = 0; //函数的私有状态
		return function() {
			return counter ++;
		};
	}());
	
	//这段代码定义了一个立即调用函数(函数的开始带有左圆括号),因此是这个函数的返回值赋值给变量uniqueInteger,
	//嵌套的函数可以访问作用域内的变量,而且可以访问外部函数中定义的counter变量

像counter一样的私有变量不是只能用在一个单独的闭包内,在同一个外部函数内定义的多个嵌套函数也可以访问它,这多个嵌套函数都共享一个作用域链:

	function counter () {
		var n = 0;
		retur {
			counter: function(){
				return n++;
			},
			reset: function () { n = 0 ;}
		};
	}
	
	var c = counter(), d = counter(); //创建两个计数器
	c.count(); // => 0 ;
	d.count(); // => 0; 它们互不干扰
	c.reset(); //reset() 和 count() 方法共享状态
	c.count(); // => 0,因为重置了c
	d.count(); //=> 1,没有重置d
	function counter (n) { //函数参数n是一个私有变量
		return {
			get count () {
				return n++;
			}
			set count(m) {
				if(m >= n) n = m;
				else throw Error ("...")
			}
		};
		
	}
	
	var c = counter(1000);
	c.count // =>1000
	c.count //=> 1001
	c.count = 2000
	c.count // => 2000
	c.count = 2000 //=> Error	
	
	function constfuncs () {
		var funcs = [];
		for ( var i = 0; i < 10; i++) {
			funcs[i] = function () {
				return i ;
			};
			return funcs;
		}
	}
	
	var funcs = constfuncs();
	funcs[5](); 

 

函数的属性和方法

length属性

arguments.length表示传入函数的实参的个数。

 

下面的代码定义一个名叫check()的函数,从另外一个函数给它传入arguments数组,它比较arguments.length和arguments.callee.

length来判断所传入的实参个数是否正确。

	function check (args) {
		var actual = args.length; //实参的真实个数
		var expected = args.callee.length; //期望的实参个数
		if ( actual !== expected)
		throw Error("...")
	}
	
	function f (x,y,z) {
		check (arguments); //检查实参个数和期望的个数是否一致
		return x + y = z; //再执行函数的后续
	}
	

 

prototype

每个函数都包含一个prototype属性,这个属性是指向一个对象的引用,这个对象称做为 原型对象。

 

call() 和 apply()

f.call(o);
f.apply(o);

o.m = f(); //将f存储为o的临时方法
o.m (); //调用它,不传入参数
delete o.m; //将临时方法删除
function trace(o,m) {
		var original = o[m]; //在闭包中保存原始方法
		o[m] = function () { //定义新的方法
			console.log( new Date(), "Entering:", m); //输出日志信息
			var result = original.apply(this,arguments); //调用原始函数
			console.log(new Date(),"Exiting:", m);
			return result ; //返回结果 
		}
	}

 

 

bind()

这个方法的作用就是将函数绑定至某个对象。当在函数f()上调用bind()方法并传入一个对象o作为参数,这个方法将返回一个新的函数。

	function f(y) {
		return this.x + y ;
	}
	var o = { x: 1 }; //将要绑定的对象
	var g = f.bind(o); //通过调用 g(x)来调用o.f(x)
	g(2); //=> 3



	
	//可以通过如下代码轻易地实现这种绑定:
	//返回一个函数,通过调用它来调用o中的方法f(),传递它所有的实参
	f(), //传递它所有的实参
	function bind (f,o) {
		if(f.bind) return f.bind(o); //如果bind()的方法存在,使用bind()
		else f.apply(o,arguments);
	}
	var sum = function(x,y) {
		return x+y;
	} //返回两个实参的和值 
	//创建一个类似sum的新函数,但this的值 绑定到Null
	var sunc = sum.bind(null,1);
	succ(2)  // => 3:x绑定到1,并传入2作为实参y
	
	function f(y,z) {
		return this.x + y + z; //另外一个做累加计算的函数
	}
	var g = f.bind({x:1},2); //绑定this 和 y
	g(3) // => 6: this.x绑定到1,y绑定到2,z绑定到3

 

toStirng()

返回一个字符串

 

Function()构造函数

var f = new Function("x", "y", "return x*y;");

var f = function(x,y) { return x*y};

 

记忆

将上次的计算结果 缓存起来,这种缓存技巧叫做记忆。

	//返回f()的带有记忆功能的版本
	//只有当f()的 实参的字符串表示 不相同时它才会工作
	function memorize(f){
		var cache(); //将值促成在闭包内
		return function() {
			//将实参转化为字符串形式,并将其用做缓存的键
			var key = arguments.length + Array.prototype.koin.call(arguments,",");
			if(key in cache) return cache[key];
			else return cache[key] = f.apply(this,arguments);
		}
	}
	

 

 

 

你可能感兴趣的:(javascript)