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. 效果图