• javascript基础知识-函数


    1.javascript中函数有两种定义方式:

    函数语句定义和表达式定义

    //函数有定义
    function test(){
        console.log("This is a function");
    }
    
    //表达式定义
    var f = function(a){
        return Math.sqrt(a);
    };

    2.函数调用方式有以下四种:

    1)作为函数

    2)作为方法

    3)作为构造函数

    4)通过它们的call()和apply()方法间接调用

    3.关键词this没有作用域的限制,不是变量,也不是属性名,是一个关键字。

    如果嵌套函数作为方法调用,其this的值指向调用它的对象;如果嵌套函数作为函数调用,其this值不是全局变量(非严格模式下)就是undefined(严格模式下)。

    var o = {
        m: function(){
            var self = this;
            console.log(this);  //this代表o
            f();
    
            function f(){
                console.log(this);  //this代表全局对象或者undefined
                console.log(self);  //self代表o
            }
        }
    }

    4.闭包

    闭包的概念:是指函数变量可以被隐藏于作用域内,因此看起来是函数将变量包裹起来。

    百度的闭包定义:闭包是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。

    Javascript采用词法作用域,也就是说,函数的执行依赖于变量的作用域。这个作用域是在函数定义时决定的,而不是在函数调用时决定的。

    理解闭包首先要了解嵌套函数的词法作用域规则:

    var scope = "global scope";
    function checkscope(){
        var scope = "local scope";
        function f(){
            return scope;
        }
        return f();
    }
    
    checkscope();   //返回local scope

    修改一下上述代码:

    var scope = "global scope";
    function checkscope(){
        var scope = "local scope";
        function f(){
            return scope;
        }
        return f;
    }
    
    checkscope()();   //返回local scope

    为什么上述代码也返回local scope呢?

    Javascript函数的执行用到了作用域链,这个作用域链是函数定义的时候创建的,嵌套函数f()定义在这个作用域链例里,其中的变量scope一定是局部变量。不管在何时何地执行函数f(),这种绑定在执行f()时依然有效。

    这就是闭包的特性导致的。函数定义时的作用域链到函数执行时依然有效,这也是词法作用域规则。

    闭包的这个特性可以捕获到局部变量(和参数),并一直保存下来,看起来像这些变量绑定到了在其中定义它们的外部函数。

    关于作用域链的补充:

    定义:每一段Javascript代码(全局代码或函数)都有一个与之关联的作用域链。作用域链可以描绘成是一个对象列表或者链表,这组对象定义了这段代码作用域中的变量。

    每次调用Javascript的时候,都会为之创建一个新的对象来保存局部变量,把这个对象添加到作用域链中。当函数返回的时候,就从作用域链中将这个绑定变量的对象删除。如果不存在嵌套的函数,也没有其他引用指向这个绑定对象,它就会被当做垃圾回收掉。如果定义了嵌套的函数,每个嵌套的函数都各自对应一个作用域链,并且这个作用域链指向一个变量绑定对象。但如果这些嵌套的函数对象在外部函数中保存下来,那么他们也会和所指向的变量绑定对象一样当做垃圾回收。但是如果这个函数定义了嵌套函数,并且将它作为返回值返回或者保存在某处的属性中,这是就会有一个外部引用指向这个嵌套的函数。它就不会被当做垃圾回收,并且它所指向的变量绑定对象也不会被当做垃圾回收掉。

    下面是利用闭包技术共享私有状态的方法:

    function addPrivateProperty(o,name,predicate){
        var value;  //这是一个属性
        
        //getter方法简单地将其返回
        o["get" + name] = function(){return value;}
        
        //setter方法首先检查值是否合法,若不合法就抛出异常
        //否则就将其存储起来
        o["set" + name] = function(v){
            if(predicate && !predicate(v)){
                throw Error("set" + name + ":invalid value " + v);
            }else{
                value = v;
            }
        };
    }
    
    //下面展示了addPrivateProperty()方法
    var o = {}; // 设置一个空对象
    
    //增加属性存取方法getName()和setName()
    //确保只允许字符串值
    addPrivateProperty(o, "Name", function(x){return typeof x == "string";});
    
    o.setName("Frank");              //设置属性
    console.log(o.getName());     //得到属性
    o.setName(o);                       //试图设置一个错误类型的值

    利用闭包定义函数,进行缓存记忆:

    function memorize(f){
        var cache = {};
        return function(){
            var key = arguments.length +  Array.prototype.join.call(arguments,",");
            if(key in cache) return cache[key];
            else return cache[key] = f.apply(this,arguments);
        }
    }
  • 相关阅读:
    栈· 用一个栈实现另一个栈的排序
    Array+DP leetcode-11.装更多的水
    string+DP leetcode-4.最长回文子串
    leetcode-3 最长无重复字串
    栈 · 有getMin功能的栈O(1)
    VS OpenCV imread imwrite nameWindow等相关报错问题
    socket字符流循环截取
    jsp:set/getProperty底层实现的探究
    关于C++11右值引用和移动语义的探究
    VS fopen sprinft ... unsafe 问题
  • 原文地址:https://www.cnblogs.com/zjtTT/p/5022609.html
Copyright © 2020-2023  润新知