函数表达式

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
</head>

<body>
    <script type="text/javascript">
    // 函数声明式  函数表达式

    // 关于函数声明具有  函数声明提升

    function functionName(arg0, arg1, arg2) {
        // 函数体
    }


    sayHi()

    function sayHi() {
        alert("hi")
    }

    // 函数表达式  这种函数叫做 匿名函数 也叫做 拉姆达函数

    var functionName = function(arg0, arg1, arg2) {
        // 函数体
    }

    sayHi() //错误  函数不存在

    var sayHi = function() {
        alert("hi")
    }

    // 函数声明 和函数表达式 最大的区别是 函数提升 

    // 不能这样做

    if (condition) {
        function sayHi() {
            alert("hi")
        }
    } else {
        function sayHi() {
            alert("Yo!")
        }
    }

    // 上面代码 浏览器解析出来的最终结果是         function sayHi() {alert("Yo!")}

    // 关键是。函数和变量的预解析

    // 可以这样做

    var sayHi
    if (condition) {
        sayHi = function() {
            alert("hi")
        }
    } else {
        sayHi = function() {
            alert("Yo!")
        }
    }

    function createComparisonFunction(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
            }
        }
    }

    // 递归  递归函数就是 在一个函数名 通过名字调用自身的情况下构成

    function factorial(num) {
        if (num < 1) {
            return 1
        } else {
            return num * factorial(num - 1)
        }
    }


    var anotherFactorial = factorial

    factorial = null

    alert(anotherFactorial(4)) //出错

    // 解决方案 arguments.callee 是一个指向 正在执行的函数的指针

    function factorial(num) {
        if (num < 1) {
            return 1
        } else {
            return num * arguments.callee(num - 1)
        }
    }

    // 如果在严格模式下 可以用命名函数表达式 达到相同的效果

    var factorial = (function f(num) {
        if (num < 1) {
            return 1
        } else {
            return num * f(num - 1)
        }
    })

    // 7.2 闭包  闭包是指定有权访问另一个函数作用域中变量的函数   闭包常见方式。在一个函数内部创建另一个函数


    function createComparisonFunction(propertyName) {
        return function(object1, object2) {
            var value1 = object1[propertyName]; // ...
            var value2 = object2[propertyName] // ...

            if (value1 < value2) {
                return -1
            } else(value1 > value2) {
                return 1
            } else {
                return 0
            }
        }
    }

    // 这里的作用域链 和 原型链 区分一下

    // 当一个函数 被调用的时候 会创建 execution content (执行环境) 及其相应的作用域链 
    // 使用 arguments 和其它命名参数值来处初始化函数的活动对象 (activation object) 在作用域链 外部函数对象处于第二位  外部函数的外部函数对象 处于第三位 一次类推 直至 作用链条终点的全局执行环境

    function compare(value1, value2) {
        if (value1 < value2) {
            return -1
        } else if (value1 > value2) {
            return 1
        } else {
            return 0
        }
    }
    var result = compare(5, 10)

    // 7.2.1 闭包与变量

    function createFunctions() {
        var result = new Array()

        for (var i = 0; i < 10; i++) {
            result[i] = function() {
                return i
            }
        }
        return result
    }
    createFunctions()
    // 匿名函数强行闭包
    function createFunctions() {
        var result = new Array()
        for (var i = 0; i < 10; i++) {
            result[i] = function(num) {
                return function() {
                    return num
                }
            }(i)
        }
        return result
    }

    // 7.22 关于this 的对象。this 对象 是在运行基本函数的执行环境中绑定的

    // this 在全局函数函数中 是window  而函数作为某个对象的方法调用时 this 就是那个对象

    // 匿名函数的执行环境 具有全局性

    var name = "The Window"

    var object = {
        name: "My Object",
        getNmaeFunc: function() {
            return function() {
                return this.name
            }
        }
    }

    console.log(object.getNmaeFunc()()) // "The Window" (在非严格模式下) 

    // 闭包和匿名函数 唯一的区别就是  函数有没有 有权访问另一个函数作用域中的变量

    var name = "The Window"

    var object = {
        name: "My Object",
        getNameFunc: function() {
            var that = this
            return function() {
                return that.name
            }
        }
    }


    console.log(object.getNmaeFunc()())

    // 在通过 call 后者apply 改变函数执行环境的情况下 this 就会指向其它对象


    var name = "The Window"

    var object = {
        name: "My Object",
        getName: function() {
            return this.name
        }
    }

    object.getName() // My Object
    (object.getName)() //  My Object
    (object.getName = object.getName)() // The Window

    // 内存泄漏

    function assignHandler() {
        var element = document.getElementbyId("someElement")

        element.onclick = function() {
            alert(element.id)
        }
    }

    // 内存正常收回

    function assignHandler() {
        var element = document.getElementbyId("someElement")
        var id = element.id
        element.onclick = function() {
            alert(id)
        }
        element.null
    }

    //  模仿块计作用域

    function outputNumbers(count) {
        for (var i = 0; i < count; i++) {
            alert(i)
        }

        alert(i)
    }

    // 匿名函数 块级作用域

    (function() {
        // 这里是块级作用域
    })()

    var someFuncton = function() {
        // 这里是块级作用域
    }
    someFuncton()


    function() {
        //  这里是块级作用域  也叫做 私有作用域
    }() // 会报错  functoin 关键字作为函数声明的开始 函数声明后不能跟圆括号 

    (function() {

    })()

    function outputNumbers(count) {
        (function() {
            for (var i = 0; i < count; i++) {
                alert(i)
            }
        })()
        alert(i) // 这里会报错
    }


    // 在很多开发人员 共同参与的大型项目 过多的全局变量和函数 容易导致 命名冲突 而通过创建私有作用域

    (function() {
        var now = new Date()
        if (new.getMonth() == 0 && now.getDate() == 1) {
            alert("Happy new Year")
        }
    })()

    // 其中now 是匿名函数中的局部变量 

    // 7.4 私有变量 任何函数中定义的变量, 都可以认为是私有变量  私有变量 包括 函数参数 局部变量 和在函数内部定义的其它函数

    function add(num1, num2) {
        var sum = num1 + num2;
        return sum
    }


    // 我们把 有权访问私有变量和私有函数的 公有方法 称为特权方法  创建特权方法 有两种 第一种 构造函数


    function MyObject() {
        // 私有变量 和私有函数
        var privateVariable = 10

        function privateFunction() {
            return false
        }

        this.publicMethod = function() {
            privateVariable++
            console.log(privateVariable)
            return privateFunction();
        }

    }
    var instance = new MyObject()

    // 利用私有和特权成员 可以隐藏哪些不应该被直接修改的数据

    function Person(name) {
        this.getName = function() {
            return name
        }
        this.setName = function(value) {
            name = value
        }
    }

    var person1 = new Person("Nicholas");
    person1.getName()

    person1.setName("Greg")
    person1.getName()

    // 构造函数 每个实例都会创建同样的一组方法

    // 7.4.1 静态私有变量

    (function() {
        // 私有变量和私有函数

        var privateVariable = 10;

        function privateFunction() {
            return false
        }

        // 构造函数

        MyObject = function() {

        };

        // 公有/ 特权方法

        MyObject.prototype.publicMethod = function() {
            privateVariable++
            return privateFunction();
        }

    })()

    // 利用原型 实现所有的方法都是共享的
    (function() {
        var name = '';
        Person = function(value) {
            name = value
        }

        Person.prototype.getName = function() {
            return name
        }
        Person.prototype.setName = function(value) {
            name = value
        }
    })()

    var person1 = new Person("Nicholas");
    person1.getName()
    person1.setName("Greg")
    person1.getName()

    var person2 = new Person("Michael");

    person1.getName()
    person2.getName()

    // person2.__proto__  ===  person2.__proto__

    // 多查找作用域链一个层次 就会在一定程度上影响查找的速度 这正是使用闭包和私有变量的一个明显不足之处

    // 模块模式  7.4.2 

    // 模块模式 就是为单例 创建私有变量 和特权方法 singleton (只有一个对象的实例)

    var singleton = {
        name: value,
        method: function() {
            // 这里是方法的代码
        }
    }


    var singleton = function() {
        //  私有变量 和私有方法

        var privateVariable = 10;

        function privateFunction() {
            return false;
        }
        // 特权 公有方法和属性
        return {
            publicProperty: true,
            publicMethod: function() {
                privateVariable++;
                return privateFunction()
            }

        }
    }

    var instance = new singleton()

    // 例子

    var application = function() {
        // 私有变量 和函数

        var components = new Array()

        // 初始化
        // components.push(new BaseComponent())

        return {
            getComponentCount: function() {
                return components.length
            },

            registerComponent: function(component) {
                if (typeof component == "object") {
                    components.push(component)
                }
            }
        }

    }


    // 模块模式  7.4.3  增强的那么模块模式

    var singletion = function() {
        //  私有变量 和私有方法

        var privateVariable = 10;

        function privateFunction() {
            return false;
        }
        // 创建对象 
        CustomType = function() {}
        var object = new CustomType()

        // 添加特权 /公有属性和方法
        object.publicProperty = true;
        object.publicMethod = function() {
            privateVariable++;
            return privateFunction()
        }

        return object;
    }()


    // 
    var application = function() {

        //  私有变量 和私有方法

        var components = new Array()

        // 初始化
        var BaseComponent = function() {

        }
        components.push(new BaseComponent())
        // 创建一个局部 appliction 的副本
        var app = new BaseComponent()

        app.getComponentCount = function() {
            return components.length
        }
        app.registerComponent = function(component) {
            if (typeof component == "object") {
                components.push(component)
            }
        }
        return app
    }()
    </script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值