心情:自己挖的坑,哭着也要填完。(>_<)~~~~
4.1 Function()对象概要
函数是代码语句的容器,使用圆括号操作符()来调用。
var addNumbersA = new Function('num1', 'num2', 'return num1 + num2');
console.log(addNumbersA(2, 2)); // 输出 4
// 也可以使用字面量
var addNumbersB = function(num1, num2) {return num1 + num2;};
console.log(addNumbersB(2, 2)); // 输出 4
从最基本的形式来说,函数只是可执行语句的唯一作用域。
4.2 Function()参数
var addFunction = new Function('num1', 'num2', 'return num1 + num2');
var timesFunction = new Function('num1,num2', 'return num1 * num2');
console.log(addFunction(2,2),timesFunction(2,2)); // 输出 '2 2'
var addFunction = function(num1, num2) {return num1 + num2;};
function addFunction(num1, num2) {return num1 + num2;}
4.3 Function()属性和方法
属性
- prototype
4.4 Function对象实例属性和方法
实例属性
- arguments
- constructor
- lenth
实例方法
- apply()
- call()
- toString()
4.5 函数总有返回值
所有函数都要返回一个值,如果不指定要返回的值,则返回值是undefined。
var sayHi = function() {
return 'Hi';
};
console.log(sayHi()); // logs "Hi"
var yelp = function() {
console.log('I am yelping!');
}
console.log(yelp() === undefined);
4.6 函数是“一等公民”(不仅语法,还有值)
在javaScript中,函数是一个对象,也是一个值。
函数可以存储在一个变量,数组或者对象中。函数可以传递给函数,并由函数返回。函数拥有属性,因为它是一个对象。
var funcA = function(){}; // 调用方式: funcA()
var funcB = [function(){}]; // 调用方式: funcB[0]()
var funcC = {method: function(){}}; //调用方式 funcC.method() or funcC['method']()
var funcD = function(func){
return func
};
var runFuncPassedToFuncD = funcD(function(){console.log('Hi');});
runFuncPassedToFuncD();
var funcE = function(){};
funcE.answer = 'yup'; // 实例化属性
console.log(funcE.answer); // 输出 'yup'
4.7 函数的参数传递给
调用函数时,参数是将值传递给函数作用域的工具。
var addFunction = function(number1, number2) {
var sum = number1 + number2;
return sum;
}
console.log(addFunction(3, 3)); //logs 6
4.8 this 和 arguments 适用于所有函数
arguments是一种类数组对象,他包含所有传递给参数的对象。
var add = function() {
return arguments[0] + arguments[1];
};
console.log(add(4, 4)); // returns 8
this关键字是对包含函数的对象的引用。
var myObject1 = {
name: 'myObject1',
myMethod: function(){console.log(this.name);}
};
myObject1.myMethod(); // logs 'myObject1'
var myObject2 = function(){console.log(this);};
myObject2(); // logs Window
4.9 arguments.callee属性
arguments的callee属性,它是指对当前函数的引用。
自我引用——该属性可以用于从函数的作用域内引用函数。
var foo = function foo() {
console.log(arguments.callee); // 输出 foo()
// callee 可以对 foo 函数进行递归调用 ( arguments.callee())
}();
4.10 函数实例的length属性和arguments.length
- Function()实例的length属性,可以获得函数所需要的参数总量
- arguments.length给出的是调用时发送给函数的参数数量
- arguments.callee.length
var myFunction = function(z, s, d, e, r, m, q) {
return myFunction.length;
};
console.log(myFunction()); //输出 7
var myFunction = function(z, s, d) {
return arguments.length;
};
console.log(myFunction()); // 输出 0 因为没有传入任何参数
4.11 重定义函数参数
var foo = false;
var bar = false;
var myFunction = function(foo, bar) {
arguments[0] = true; // 方法1:使用arguments索引
bar = true; // 方法2:直接为参数指定一个新值
console.log(arguments[0], bar); // 输出 true true
}
myFunction();
4.12 代码执行完成前取消函数执行
在函数的任意点上通过使用return关键字来取消函数执行。
var add = function(x, y) {
// 如果不是数字,返回错误
if (typeof x !== 'number' || typeof y !== 'number') {return 'pass in numbers';}
return x + y;
}
console.log(add(3,3)); // 输出 6
console.log(add('2','2')); // 输出 'pass in numbers'
4.13 定义函数(语句、表达式或构造函数)
定义函数有三种不同的方式:函数构造函数,函数语句和函数表达式。
/* 函数构造函数:最后一个参数是函数逻辑,之前都是参数 */
var addConstructor = new Function('x', 'y', 'return x + y');
// 函数语句
function addStatement(x, y) {
return x + y;
}
// 函数表达式
var addExpression = function(x, y) {
return x + y;
};
console.log(addConstructor(2,2), addStatement (2,2), addExpression (2,2));
//命名函数表达式
var add = function add (x, y) { return x + y; }
4.14 调用函数(函数、方法、构造函数或call()和apply())
使用4种不同场景或模式调用函数:
- 作为函数
// 函数模式
var myFunction = function(){return 'foo'};
console.log(myFunction()); // log 'foo'
- 作为方法
// 方法模式
var myObject = {myFunction: function(){return 'bar';}}
console.log(myObject.myFunction()); // log 'bar'
- 作为构造函数
// 构造函数模式
var Cody = function(){
this.living = true;
this.age = 33;
this.gender = 'male';
this.getGender = function() {return this.gender;};
}
var cody = new Cody(); // 通过Cody构造函数调用
console.log(cody); // 输出 cody 对象和属性
- 使用apply()或者call()
// apply() and call() 模式
var greet = {
runGreet: function(){
console.log(this.name,arguments[0],arguments[1]);
}
}
var cody = {name:'cody'};
var lisa = {name:'lisa'};
//在 cody 对象上调用 runGreet 函数
greet.runGreet.call(cody,'foo','bar'); //输出 cody foo bar
//在 lisa 对象上调用 runGreet 函数
greet.runGreet.apply(lisa, ['foo','bar']); //输出 lisa foo bar
/* 注意 call() 和 apply() 之间的区别是函数调用时,参数传递的不同。前者传递多个分开的参数,后者传递多个参数组成的数组 */
4.15 匿名函数
匿名函数是一种没有给出标识符的函数。
匿名函数主要用于将函数作为参数传递给另一个函数。
// 创建一个函数来执行匿名函数
var sayHi = function(f){
f(); // 调用匿名函数
}
// 将匿名函数作为参数传递
sayHi(function(){console.log('hi');}); // 输出 'hi'
4.16 自调用的函数表达式
在定义一个函数表达式后,加上圆括号,便可立即调用改函数表达式。
var sayHi = function () { console.log('Hi'); } ();// 输出'Hi'
4.17 自调用的匿名函数表达式
创建一个自调用的匿名函数语句,这叫做自调用的匿名函数。
// 最经常使用的匿名函数
(function(msg) {
console.log(msg);
})('Hi');
// 看起来有点不一样,但效果一样
(function(msg) {
console.log(msg)
}('Hi'));
// 更简短的方式
!function sayHi(msg) {console.log(msg);}('Hi');
// 注意,下面的的代码不行
//function sayHi() {console.log('hi');}();
注意:根据ECMAScript标准,如果要立即调用函数,需要使用函数外面的圆括号(或任何将函数转换为表达式的符号)。
4.18 函数可以嵌套
函数可以无限嵌套在其他函数内部
var foo = function () {
var bar = function () {
var goo = function () {
console.log(this);
} ();
} ();
} ();
4.19 给函数传递参数,从函数返回函数
由于函数是一个值,并且可以将任何类型的值传递给函数,因此函数可以被传递给函数,也可以返回其他函数。(高阶函数)
var foo = function(f) { //传入函数
return f; //返回函数
}
var bar = foo(function() {console.log('Hi');});
bar(); //输出 'Hi'
函数可以像其他任何值一样被传递。
4.20 函数定义之前调用(函数提升)
在代码运行之前,函数语句其实已经被编译器解释,并添加至执行堆栈/上下文。
var speak = function() {
sayYo(); // sayYo() 还没有被定义,但依然可以执行并输出 'yo'
function sayYo() {console.log('Yo');}
}();
注意:被定义为“函数表达式”的函数没有被提升,只有“函数语句”被提升。
4.21 函数可以调用自身(递归)
函数调用自身是完全合法的。启动一个函数,然后通过该函数调用本身。
function cutDownForm (num) {
console.log(num);
num--;
if (num < 0) { return false; }
cutDownForm (num);
}
cutDownForm (2);
匿名函数可以通过arguments.callee进行递归
(function (num) {
console.log(num);
num--;
if (num < 0) { return false; }
arguments.callee(num);
} (2));