052_Function对象

1. Function对象

1.1. Function类可以表示开发者定义的任何函数。

1.2. 使用Function()构造函数可用动态创建函数。

1.3. JavaScript函数实际上是功能完整的对象。

1.4. 语法

new Function ([arg1[, arg2[, ...argN]],] functionBody)

1.5. 参数

1.5.1. arg1, arg2, ... argN被函数使用的参数的名称。

1.5.2. functionBody一个含有包括函数定义的JavaScript语句的字符串。

1.6. 实例

function doAdd1(a, b) {
	return a + b;
}

var doAdd2 = new Function('a', 'b', 'return a + b;');

1.7. 通过Function的方式创建函数, 有助于我们理解, 函数只不过是一种引用类型, 函数名是指向函数对象的变量。

1.8. 使用Function创建函数例子

1.8.1. 代码

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="utf-8" />
		<title>Function对象</title>
	</head>
	<body>
		<script type="text/javascript">
			function doAdd1(a, b) {
				return a + b;
			}

			var doAdd2 = new Function('a', 'b', 'return a + b;');

			document.write(doAdd1(8, 9) + '<br />');
			document.write(doAdd2(8, 9));
		</script>
	</body>
</html>

1.8.2. 效果图

1.9. 尽管可以使用Function构造函数创建函数, 但最好不要使用它, 因为用它定义函数比用传统方式要慢得多。不过, 所有函数都应看作Function类的实例。

1.10. 函数名是指向函数的变量, 那么可以把函数作为参数传递给另一个函数:

function doAdd(a, b) {
	return a + b;
}

function doAddWrap(doAdd, a, b) {
	document.write('a = ' + a + '<br />');
	document.write('b = ' + b + '<br />');
	return doAdd(a, b);
}

1.11. 使用函数当作参数例子

1.11.1. 代码

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="utf-8" />
		<title>函数参数</title>
	</head>
	<body>
		<script type="text/javascript">
			function doAdd(a, b) {
				return a + b;
			}

			function doAddWrap(doAdd, a, b) {
				document.write('a = ' + a + '<br />');
				document.write('b = ' + b + '<br />');
				return doAdd(a, b);
			}

			document.write(doAddWrap(doAdd, 8, 9));
		</script>
	</body>
</html>

1.11.2. 效果图

2. Function对象属性

3. length属性

3.1. length属性指明函数的形参个数。

3.2. length是函数对象的一个属性值, 指该函数有多少个必须要传入的参数, 即形参的个数。形参的数量不包括剩余参数个数, 仅包括第一个具有默认值之前的参数个数。

4. name属性

4.1. name属性返回一个函数声明的名称。

4.2. 使用new Function(...)构造器创建的函数名称为anonymous(匿名)。

5. Function对象方法

6. apply()方法

6.1. apply()方法调用一个具有给定this值的函数, 以及以一个数组(或类数组对象)的形式提供的参数。

6.2. 语法

func.apply(thisArg, [argsArray])

6.3. 参数

6.3.1. thisArg可选的。在func函数运行时使用的this值。请注意, this可能不是该方法看到的实际值: 如果这个函数处于非严格模式下, 则指定为null或undefined时会自动替换为指向全局对象, 原始值会被包装。

6.3.2. argsArray可选的。一个数组或者类数组对象, 其中的数组元素将作为单独的参数传给func函数。如果该参数的值为null或 undefined, 则表示不需要传入任何参数。

6.4. 本例调用person的fullName方法, 并用于person1:

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName:"Bill",
    lastName: "Gates",
}
person.fullName.apply(person1);  // 将返回 "Bill Gates"

6.5. 带参数的apply()方法:

var person = {
  	fullName: function(city, country) {
    	return this.firstName + " " + this.lastName + "," + city + "," + country;
  	}
}
var person1 = {
  	firstName:"Bill",
  	lastName: "Gates"
}
person.fullName.apply(person1, ["Seattle", "USA"]);

7. call()方法

7.1. call()方法使用一个指定的this值和单独给出的一个或多个参数来调用一个函数。

7.2. 语法

function.call(thisArg, arg1, arg2, ...)

7.3. 参数

7.3.1. thisArg可选的。在function函数运行时使用的this值。请注意, this可能不是该方法看到的实际值: 如果这个函数处于非严格模式下, 则指定为null或undefined时会自动替换为指向全局对象, 原始值会被包装。

7.3.2. arg1, arg2, ...指定的参数列表。

7.4. apply()方法与call()方法非常相似:

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName: "Bill",
    lastName: "Gates",
}
person.fullName.call(person1);  // 将返回 "Bill Gates"

7.5. call()和apply()之间的区别:

7.5.1. call()方法分别接受参数。

7.5.2. apply()方法接受数组形式的参数。

8. bind()方法

8.1. bind()方法创建一个新的函数, 在bind()被调用时, 这个新函数的this被指定为bind()的第一个参数, 而其余参数将作为新函数的参数, 供调用时使用。

8.2. 语法

function.bind(thisArg[, arg1[, arg2[, ...]]])

8.3. 参数

8.3.1. thisArg调用绑定函数时作为this参数传递给目标函数的值。如果使用new运算符构造绑定函数, 则忽略该值。当使用bind在setTimeout中创建一个函数(作为回调提供)时, 作为thisArg传递的任何原始值都将转换为 object。如果bind函数的参数列表为空, 或者thisArg是null或undefined, 执行作用域的this将被视为新函数的thisArg。

8.3.2. arg1, arg2, ...当目标函数被调用时, 被预置入绑定函数的参数列表中的参数。

9. toString()方法

9.1. toString()方法返回一个表示当前函数源代码的字符串。

9.2. 语法

function.toString()

9.3. Function对象覆盖了从Object继承来的toString方法。对于用户定义的Function对象, toString方法返回一个字符串, 其中包含用于定义函数的源文本段。

9.4. 如果是在内置函数或由Function.prototype.bind返回的函数上调用toString(), 则toString()返回原生代码字符串。

9.5. 若是在由Function构造器生成的函数上调用toString(), 则toString()返回创建后的函数源码, 包括形参和函数体, 函数名为"anonymous"。

10. 例子

10.1. 代码

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="utf-8" />
		<title>Function对象</title>
	</head>
	<body>
		<script type="text/javascript">
			function doPlus(){}
			function doMinus(param1, param2){} 
			function doMultiply(param1, param2, param3 = 0, param4, param5){}
			function doDivision(...args){}
			var sum = new Function('a', 'b', 'return a + b;');
			var remainder = new Function();

			document.write(doPlus + ', ' + doPlus.constructor + ', ' + (doPlus.constructor === Function) + '<br />');
			document.write(doMinus + ', ' + doMinus.constructor + ', ' + (doMinus.constructor === Function) + '<br />');
			document.write(doMultiply + ', ' + doMultiply.constructor + ', ' + (doMultiply.constructor === Function) + '<br />');
			document.write(doDivision + ', ' + doDivision.constructor + ', ' + (doDivision.constructor === Function) + '<br />');
			document.write(sum + ', ' + sum.constructor + ', ' + (sum.constructor === Function) + '<br />');
			document.write(remainder + ', ' + remainder.constructor + ', ' + (remainder.constructor === Function) + '<br />');
			document.write(Function + ', ' + Function.constructor + ', ' + (Function.constructor === Function)  + '<hr />');

			document.write('doPlus函数的形参个数: ' + doPlus.length + '<br />');
			document.write('doMinus函数的形参个数: ' + doMinus.length + '<br />');
			document.write('doMultiply函数的形参个数: ' + doMultiply.length + '<br />');
			document.write('doDivision函数的形参个数: ' + doDivision.length + '<br />');
			document.write('sum函数的形参个数: ' + sum.length + '<br />');
			document.write('remainder函数的形参个数: ' + remainder.length + '<hr />');

			document.write('doPlus.name = ' + doPlus.name + '<br />');
			document.write('doMinus.name = ' + doMinus.name + '<br />');
			document.write('doMultiply.name = ' + doMultiply.name + '<br />');
			document.write('doDivision.name = ' + doDivision.name + '<br />');
			document.write('sum.name = ' + sum.name + '<br />');
			document.write('remainder.name = ' + remainder.name + '<br />');
			document.write('Function.name = ' + Function.name + '<hr />');
			
			var module = {
				x: 42,
				getX: function(){
					return this.x;
				}
			};

			document.write('x = ' + module.getX() + '<br />');
			var unboundGetX = module.getX;
			document.write('x = ' + unboundGetX() + '<br />');
			var boundGetX = unboundGetX.bind(module);
			document.write('unboundGetX == boundGetX: ' + (unboundGetX == boundGetX) + '<br />');
			document.write('x = ' + boundGetX() + '<hr />');

			document.write(module.getX.toString() + '<br />');
			document.write(sum.toString() + '<br />');
			document.write(Math.max.toString() + '<br />');
			document.write(boundGetX.toString() + '<hr />');

			var person = {
    			fullName: function() {
        			return this.firstName + " " + this.lastName;
    			}
			}
			var person1 = {
			    firstName:"Bill",
			    lastName: "Gates",
			}
			document.write(person.fullName.call(person1) + '<br />');
			document.write(person.fullName.apply(person1) + '<br />');
			document.write(Math.max.apply(null, [1,2,3]) + '<br />');

			var data = '123456';
			function display() {
				document.write('data value is ' + this.data + '<br />');
			}
			// 没有参数的call和applay使用的是全局对象Window
			display.call();
			display.apply();

			function ClassPeople(firstName, lastName){
				this.firstName = firstName;
				this.lastName = lastName;

				document.write('<hr />firstName = ' + firstName + ', lastName = ' + lastName + '<br />');
			}
			var cp = ClassPeople.bind();
			new cp('zhang', 'san');
			
			function fn(){
				document.body.appendChild(document.createTextNode('this = ' + this + ', typeof(this) = ' + typeof(this)));
			}
			var nfn = fn.bind(1);
			setTimeout(nfn, 1000);
		</script>
	</body>
</html>

10.2. 效果图

11. 模拟call、apply和bind方法例子

11.1. 代码

<!DOCTYPE html>
<html>
	<head>
		<title>模拟call、apply和bind方法</title>
	</head>
	<body>
		<script type="text/javascript">
			Function.prototype.mycall = function(context){
				var args = Array.prototype.slice.call(arguments, 1);
				context.__proto__.fn = this;
				// 可变参数
				context.fn(...args);
				context.__proto__.fn = undefined;
			};

			Function.prototype.myapply = function(context, args){
				if(!(args instanceof Array)){
					throw new Error("Uncaught TypeError: CreateListFromArrayLike called on non-object");
				}

				context.__proto__.fn = this;
				context.fn(...args);
				context.__proto__.fn = undefined;
			};

			Function.prototype.mybind = function(context){
				var fn = this, firsts = Array.prototype.slice.call(arguments, 1);
				return function(){
					return fn.apply(context, firsts.concat(Array.prototype.slice.call(arguments)));
				};
			};

			Function.prototype.mybind2 = function(context){
				var fn = this, afters = Array.prototype.slice.call(arguments, 1);
				return function(){
					return fn.apply(context, Array.prototype.slice.call(arguments).concat(afters));
				};
			};

			var obj = {
				fullName: function(city, country){
					document.write(this.firstName + this.lastName + "," + city + "," + country + "<br />");
				}
			};

			function ClassPeople(firstName, lastName){
				this.firstName = firstName;
				this.lastName = lastName;
			}
	
			var zs = new ClassPeople('zhang', 'san');
			obj.fullName.call(zs, 'luoyang', 'zh');
			obj.fullName.mycall(zs, 'luoyang', 'zh');
			document.write("<hr />");

			var ls = new ClassPeople('li', 'si');
			obj.fullName.apply(ls, ['shanghai', 'zh']);
			obj.fullName.myapply(ls, ['shanghai', 'zh']);
			document.write("<hr />");

			var ww = new ClassPeople('wang', 'wu');
			obj.fullName.bind(ww, 'xianggang')('zh');
			obj.fullName.mybind(ww, 'xianggang')('zh');
			obj.fullName.mybind2(ww, 'zh')('xianggang');
		</script>
	</body>
</html>

 11.2. 效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值