Contents
  1. 1. 1. Function的介绍
  2. 2. 2. 相关结论:
  3. 3. 3. 小结
  4. 4. 4. 绘制函数的原型链
  5. 5. 5. arguments对象属性(这是一个类数组,保存着的是这个)
  6. 6. 6. 函数相关属性
  7. 7. 7. 模拟函数重载
  8. 8. 8. 函数递归:
  9. 9. 9. 词法作用域: 规定变量的作用域是由变量声明的位置决定,而不是由使用变量的位置决定。
  10. 10. 10. 变量名(函数名)提升
  11. 11. 11. 在预解析阶段:
  12. 12. 12. in运算符

1. Function的介绍

  1. 创建函数的方式
    code block:

    + :  声明式
           function foo() {
           console.log(arguments);
            }
           foo(1, 2, "3", {name:'jerry'});
    
    + :  表达式
            var foo = function() {
            console.log(arguments);
            };
            foo(1, 2, "3", {name:'jerry'}, true);
    
    + :  构造函数:
    Function(arg1, arg2, ...,argN ,body)所有的参数类型均为 字符串;
    arg1, arg2, ...,argN 为可选的参数列表,表示 为 生成函数的形参列表;
    body 为必选参数,表示为 生成函数的 函数体部分。
    var  foo = new Function('val1', 'val2', 'return val1 + val2;');
    
  2. 由于函数也可以通过Function构造函数来创建,那么函数也是对象;具有proto属性

2. 相关结论:

1.  所有的函数都是Function实例。

1
2
3
4
5
6
7
// Object函数的构造函数为 Function
console.log(Object.constructor);
console.log(Array.constructor);
console.log(Date.constructor);
console.log(RegExp.constructor);
var foo = function() {};
console.log(foo.constructor);
2. 所有的函数的构造函数为Function;
1
2
3
4
5
console.log(foo.__proto__ === Function.prototype);
console.log(Object.__proto__ === Function.prototype);
console.log(Array.__proto__ === Function.prototype);
console.log(Date.__proto__ === Function.prototype);
console.log(RegExp.__proto__ === Function.prototype);
3. 所有的函数的原型对象 为 Function.prototype.
1
2
3
4
console.log( Function.prototype.__proto__ === Object.prototype );
console.log( typeof Function.prototype );
console.log(Function.prototype.prototype);
// Array -> Function.prototype -> Object.prototype -> null

3. 小结

将函数    称为 函数对象
其他对象  称为 普通对象

4. 绘制函数的原型链

5. arguments对象属性(这是一个类数组,保存着的是这个)

1>  : length 实参的个数
2>:callee 返回正在执行的函数; 应用在匿名函数递归调用
1
2
3
4
5
6
7
8
9
10
var v = (function (n) {
if (n < 1) {
return undefined;
} else if (n === 1 || n === 2) {
return 1;
} else {
return arguments.callee(n - 1) + arguments.callee(n - 2);
}
}(8));
console.log(v);

6. 函数相关属性

1>:caller 返回调用当前函数的函数
2>: length 形参的个数
3>: name   存储函数的名字

7. 模拟函数重载

在js中,没有函数重载,只能通过arguments对象进行模拟
            // 如果函数没有传递实参,就直接打印false;
    // 如果传递一个实参,就将其直接打印出来;
    // 如果传递两个实参,就将两个实参拼接起来,在打印出来;
    // 如果传递一个实参并且类型为 数字的话,就加1,在打印。
    function foo() {
        if(arguments.length === 0){
            console.log(false);
        } else if(arguments.length === 1){
            if(typeof arguments[0] === 'number'){
                console.log(arguments[0] + 1);
            } else {
                console.log(arguments[0]);
            }
        } else if(arguments.length === 2){
            console.log(arguments[0] + '' + arguments[1]);
        }
    }
    foo();
    foo(1);
    foo("JQK");
    foo('A', '2');

8. 函数递归:

1>  概念:函数调用自身
2> 经典递归案例
    a:  等差数列第n项值
    b: fibonacci数列第n项值
var v = (function (n) {
        if (n < 1) {
            return undefined;
        } else if (n === 1 || n === 2) {
            return 1;
        } else {
            return arguments.callee(n - 1) + arguments.callee(n - 2);
        }
    }(8));
    console.log(v);

9. 词法作用域: 规定变量的作用域是由变量声明的位置决定,而不是由使用变量的位置决定。

在词法作用域中,只有函数可以分割作用域。在函数内部是一个完整作用域。与外界隔离
也就是,在函数内部可以访问函数外部的数据;但是函数外部无法访问内部的数据。

10. 变量名(函数名)提升

在js预解析阶段执行的操作。
js本身是边解析边执行的。

11. 在预解析阶段:

首先,分析代码语法,如果有语法错误,就直接抛出异常。
其次,将变量名以及函数声明提升 到当前作用域最顶端。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1: 全局变量是window对象的属性
// 2:变量名提升
var a;
if( 'a' in window ){
a = 10;
} else {
a = 20;
}
console.log(a);// 10
var a = 10;
if( a in window ){
a = 10;
} else {
a = 20;
}
console.log(a);// 10

12. in运算符

1》 规则:前面的属性名字,要用字符串来表示;如果为变量,那么会将变量的值隐式转换成字符串,然后去判断变量的值是否为指定对象的属性(可以为继承过来的属性)。
2》注意: 后面的参数必须为对象;否则报错。
Contents
  1. 1. 1. Function的介绍
  2. 2. 2. 相关结论:
  3. 3. 3. 小结
  4. 4. 4. 绘制函数的原型链
  5. 5. 5. arguments对象属性(这是一个类数组,保存着的是这个)
  6. 6. 6. 函数相关属性
  7. 7. 7. 模拟函数重载
  8. 8. 8. 函数递归:
  9. 9. 9. 词法作用域: 规定变量的作用域是由变量声明的位置决定,而不是由使用变量的位置决定。
  10. 10. 10. 变量名(函数名)提升
  11. 11. 11. 在预解析阶段:
  12. 12. 12. in运算符