《JavaScript高级程序设计 (第3版)》学习笔记14:chapter_5 - 5 Function类型

这是第14篇笔记!
让学习“上瘾”,成为更好的自己!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Function_type</title>
    <script>
        /*
        函数实际上是对象,每个函数都是Function类型的实例,而且具有属性和方法
        函数名是一个指向函数对象的指针,不会与某个函数绑定
        定义函数的方式:
            a,  函数声明语法
            b,  函数表达式
            c,  使用Function()构造函数 【不推荐!!】--> 影响性能
        “函数是对象,函数名是指针”

        1,没有重载
            (见下!)



        2,函数声明和函数表达式
            区别:
                函数声明:解析器会率先读取函数声明,并使其在执行任何代码之前可以访问
                函数表达式:必须等到解析器执行到他所在的代码行,才会真正被解释执行






        3,作为值的函数
            (见下)







        4,函数内部的属性
            a, 函数内部,2个特殊对象:
                    arguments:类数组的对象,包含传入函数中的所有参数
                        callee属性:一个指针,指向拥有这个arguments对象的函数
                    this:1,指向函数执行时的当前对象,跟执行环境有关,与声明环境无关
                          2,当没有明确执行时的当前对象时,this指向全局对象window,
                          或者说当网页的全局作用域中调用函数时,this对象引用的就是window
            b, (ECMAScript 5)函数对象的属性: caller -->  保存着调用当前函数的函数的引用
                                                        如果是在全局作用域中调用当前函数,他的值是null

            c, 严格模式下, arguments.callee会错误
                           arguments.caller(ECMAScript 5)会错误(非严格为undefined)







        5,函数的属性和方法
            每个函数都包含2个属性: length  --> 函数希望接收的命名参数的个数
                                 prototype --> (第6章详解) 保存引用类型实例所有实例方法
        
            每个函数都包含2个非继承而来的方法:在特定的作用域中调用函数,等同于设置函数体this对象的值
                                         apply() --> 
                                         call() --> 
                           (ECMAScript 5)bind() --> 创建一个函数的实例,其this值会被绑定到传给bind()函数的值
        
        
        */
    // 定义函数
        // way 1:
        // function sum(num1, num2){
        //     return num1 + num2;

        // }
        // ===========way1 and way2 等价书写===================
        // // way 2:
        // var sum = function(num1, num2){
        //     return num1 + num2;
        // };

        // // way 3:
        // var sum = new Function('num1','num2','return num1 + num2');  // 不推荐!!
    
    // 函数名与包含对象指针的其他变量没有什么不同
        // function sum(num1, num2){
        //         return num1 + num2;

        //     }
    
        //     console.log(sum(12,2));
        //     var anotherSum = sum;  
        //     // sum = null;
        //     console.log(anotherSum(21,3));
        //     console.log(sum);  // 使用不带圆括号的函数名是访问“函数指针”,而非调用函数
            
    // 1,没有重载(将函数名理解为指针)
        var addSomeNumber = function(num){
            return num + 100;

        }

        addSomeNumber = function(num){
            return num + 200;

        }
    
        // console.log(addSomeNumber(200));
        // 没有重载? --> 在创建第二个函数时,实际上覆盖了引用第一个函数变量addSomeNumber

        // 2,函数声明和函数表达式

        // alert(sum(10,10));  // 不会报错
        // function sum(n1, n2){
        //     return n1 + n2;

        // }
        // 在代码执行之前,解析器通过“函数声明提升”,读取并将函数声明添加到执行环境中
        // 对代码求值时,Js引擎在第一遍会声明函数并将他们放到源代码树的顶部

        // alert(sum(10,10));  // 会报错
        // var sum = function(n1, n2){
        //     return n1 + n2;

        // }

        // 3, 作为值的函数 --> 函数名
        // 通用函数: 无论第一个参数中传递进来的是什么函数,都有返回执行第一个参数后的结果
        function callSomeFunction(someFuction, someArguments){
            return someFuction(someArguments);

        }
        
        // 例子:
        function add10(num){
            return num + 10;
        }
        var result = callSomeFunction(add10, 10);
        // console.log(result);

        // 一个函数中返回另一个函数【有用的技术】
        // 例如,假设有一个对象数组,根据某个对象属性对数组进行排序
        function createComparionFunction(propertyName){
            return function(object1, object2){
                var value1 = object1[propertyName];
                var value2 = object2[propertyName];
                if(value1 < value2){
                    return -1;
                }else if(value1 > value2){
                    return 1;
                }else{
                    return 0;
                }
            }

        }


        // 使用
        var data = [
            {
                name:'kai',
                age:23
            },
            {
                name:'lilce',
                age:34
            },
            {
                name:'cili',
                age:43
            }

        ]
        // data.sort(createComparionFunction('name'));
        // console.log(data[0].name)
        // data.sort(createComparionFunction('age'));
        // console.log(data[0].name)

        // 4,函数内部的属性
        // callee
        function factorial(num){
            if(num <= 1){
                return 1;
            }else {
                return num * factorial(num - 1);
                // 函数的执行与函数名factorial紧紧耦合在一块
            }

        }


        function factorial(num){
            if(num <= 1){
                return 1;
            }else {
                return num * arguments.callee(num - 1);
                // 无论引用函数时使用什么名字,都可以保证正常完成递归调用,消除耦合状态!!
            }

        }

        var trueFatorial = factorial;
        factorial = function(){
            return 0;
        }
        // console.log(trueFatorial(5)); // 120
        // console.log(factorial(5));  // 0

        // this: 指向函数执行时的当前对象,跟执行环境有关,与声明环境无关
        // why? --> 函数的名字仅仅是一个包含指针的变量而已!!
        // window.color = 'red';
        // var o = {color: 'blue'};
        // function sayColor(){
        //     console.log(this.color);
        // }
        // sayColor();  // 'red'
 
        // o.sayColor = sayColor;
        // o.sayColor();  // 'blue'


        var someone = {
            name: "Bob",
            showName: function(){
                alert(this.name);
            }
        };

        var other = {
            name: "Tom",
            showName: someone.showName
        };

        // other.showName();  //Tom
        // this关键字虽然是在someone.showName中声明的,但运行的时候是other.showName,
        // 因为this指向other.showName函数的当前对象,即other,故最后alert出来的是other.name

        // caller
        // function outer(){
        //     inner();
        // }
        // function inner(){
        //     // alert(inner.caller);
        //     alert(arguments.callee.caller);  // 实现松散耦合
        // }
        // outer();  // 显示outer()函数的源代码,inner.caller指向outer()

        // function inner(){
        //     return 1;
        // } 
        // inner();
        // console.log(inner.caller);  // null

        // 函数属性和方法
            // function sayName(num1, num2){
            //     return num1 + num2;

            // }
            // console.log(sayName.length);  // 2


        // apply(): 第一个参数为运行函数的作用域(常为this)
        //          第二个参数可以是Array实例,或者arguments对象
            function sum(num1, num2){
                return num1 + num2;
            }
            function callSum1(num1, num2){
                console.log(this);  // window
               
                return sum.apply(this, arguments);  // arguments对象
                
            }
            function callSum2(num1, num2){
                return sum.apply(this, [num1, num2]); // Array实例
            }
            // console.log(callSum1(10, 10));
            // console.log(callSum2(10,10));
        
        // call(): 第一个参数为运行函数的作用域,变量对象表示(常为this)
        //         其余参数必须都列举出来传递给函数
            // function sum(num1, num2){
            //     return num1 + num2;
            // }

            // function callSum(n1, n2){
            //     return sum.call(this, n1, n2);
            // }
            // console.log(callSum(20, 20));

        // apply() and call() 最强大的地方: 能够扩充函数赖以运行的作用域
        // window.color = 'red';
        // var o = {color:'blue'};

        // function sayColor(){
        //     console.log(this.color);
        // }
        // sayColor();  // red

        // sayColor.call(this);  // red
        // sayColor.call(window);  // red
        // sayColor.call(o);  // blue -->  函数的执行环境改变了

        // bind() --> 创建一个函数的实例,其this值会被绑定到传给bind()方法的对象
        window.color = 'red';
        var o = {color:'blue'};

        function sayColor(x, y){
            console.log(x + y);
            console.log(this.color);
        }
        var objectSayColor = sayColor.bind(o, 3, 5);
        objectSayColor();
        // objectSayColor();  // blue
        // sayColor()调用bind()并传入对象o, 创建了objectSayColor()函数,objectSayColor()函数的this值等于o

        // bind and call
        // bind: 改变函数的this,并且返回一个新函数(不调用函数) 
        // call: 改变函数的this,且直接调用函数

    </script>
</head>
<body>
    
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值