zoukankan      html  css  js  c++  java
  • 私人定制javascript中函数小知识点

    函数的定义

    首先在javascript中,函数就是对象,程序可以随意操控它们。比如,可以给它们设置属性,甚至调用它们的方法。函数使用function关键字来定义。它既可以用在函数定义表达式,也可以用在函数声明语句中。函数声明function后面必须要更上函数名称也就是所谓的函数名称标识符。如果是函数表达式函数名称标识符可有可无。这段重点是函数是对象,所以函数表现出来的种种行为你想想成对象,那么很多疑惑可能就恍如昨日初见。

    函数调用

    4种方式来调用javascript函数:

    1.作为函数

    就是函数名称后加上圆括号加上参数列表 例如 func(2,3); 这里需要说明的是如果函数里有没有return obj;那么改函数返回值都是undefined除非返回就是undefined值。每个函数都有默认的返回值undefined;除非给予返回值。

    2.作为方法

    如果一个对象的属性被赋值为一个函数表达式,那么该函数就被当作一个方法,而不是作为一个普通函数来调用了。

    例如:o.m=f; o.m();

    3.作为构造函数

    如果函数或方法调用之前带有关键字new,它就是构造函数调用,构造函数调用和普通的函数调用以及方法调用在实参处理,调用上下文和返回值方面都有不同。 构造函数通常不会使用return关键字,它们通常初始化新对象。

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

    再次强调javascript中的函数也是对象,和其他javascript对象一样,函数对象也可以包含方法,其中每个函数都都有两个很熟悉不过的函数call()和apply()可以用来间接地调用函数。指定上下文this值,指定参数列表。后者传入参数时需要按照数组的形式传入参数。

    函数的实参对象

    如果在调用方法时少传参数,那么其余参数都将置为undefined。那么如何知道到底传了多少参数呢,实际的参数到底是多少个呢?在函数体内,标识符arguments就是指向实参对象的引用,实参对象视一个类数组对象。

    例如

    function f(x,y,z)
    {
        if(arguments.length!=3){
        throw new Error(“arguments length is should be 3”);
        }
    }

    arguments.length是指实参个数,而f.length是指形参的个数

    callee和caller属性

    callee属性指代当前正在执行的函数,caller可以访问调用栈

    浅说闭包

    现在不得不扯到闭包,javascript采用词法作用域,就是说函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数执行时决定的。为了实现这种词法作用域,javascript函数对象的内部状态不仅包含函数逻辑代码,还必须引用当前的作用域链。函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性就叫做闭包。函数定义时的作用域链在调用函数时依然有效,但是这并不影响闭包。

    首先上一段简单的代码:

    var scope=”global scope”;
    function f(){
       var scope=“local scope”;
       function func(){return scope;}
       return func();
    }
    console.log(f()); //”local scope“

    简单解释一下,关键是变量scope在函数func定义的时候就在同一个作用域链中,而var scope=”global scope”;是在最外层的作用域中,一般都在作用域中都会存在一个变量对象来专门存放作用域链,全局变量肯定是最先被存放就进去,即压入栈底,而此时在执行调用func就会找最近的变量scope找到了,立马返回。所以就会是local scope不知道我的语言组织你能明白么?

    var scope=”global scope”;
    function f(){
       var scope=“local scope”;
       function func(){return scope;}
       return func;
    }
    console.log(f()());

    请问结果是多少?

    这个时候将javascript词法作用域的基本规则体现的很淋漓尽致,javascript函数执行用到了作用域链,这个作用域链式函数定义的时候创建的。嵌套的函数func()定义在这个作用域链里,其中变量scope一定是选取最近的局部变量,不管任何时候执行func(),这种绑定在执行func()时依然有效,因此返回为”local scope”. 多个函数共享一个作用域

    function counterfun(){ 
        var n=0; 
        return{ 
             count:function(){return n++;}, 
             reset:function(){return n=0;} 
            }; 
        } 
    var c=counterfun(),d=counterfun(); 
    console.log(c.count()); //0 
    console.log(c.reset()); //0 
    console.log(d.count()); //0 
    console.log(c.reset()); //0 
    console.log(d.count());//1

    分析:因为函数count和reset共享一个属性,所以如果c.count()和c.reset()都会改变n的值并且相互影响,但是影响不了d.count()和d.reset()因为它们创建了各自独立的作用域链。 但是为什么n的值会被保存下来呢?此时你再回过头看看scope变量的那个例子道理一样,用return返回函数时都已经将私有变量保存起来了,下次再执行时肯定还是取这段作用域中的变量来操作。

    易出错且经典的例子

    如下:

    function constfuncs(){ 
        var funcs=[]; 
        for(var i=0;i<10;i++) 
            funcs[i]=function(){return i;}; 
            return funcs; 
    } 
    var funcs=constfuncs(); 
    console.log(funcs[5]());//输出是什么呢?

    这个应该不会出错吧。必须是10,因为这里所有的函数funcs[i]都共享一个作用域链其中变量i同样是共享。所以最终是循环结束的最大值10 那接下来的这个呢?

    function constfunc(v){return function(){return v;};} 
    var funcs=[]; 
    for(var i=0;i<10;i++) funcs[i]=constfunc(i);
    console.log(funcs[5]());//输出是什么呢?

    输出是5,结果是我们预期的。 这里如果按照所有的函数作用域是定义的时候就确定了的,理解起来比较费劲么,不管你信不信,反正我是中枪了。 从函数嵌套来理解,因为函数中返回函数嵌套时必须会将函数及其作用域链保存起来,这样就新创建了一个作用域链,其中的变量i也就被保存起来赋值给v了,每每return一次就会新创建一个作用域链。所以得到的v就是当时保存的i值。

    prototype属性

    每个函数都用一个prototype属性,请记住它是函的一个属性,尽管这个prototype我们总是称之为对象,但是它确实是函数的一个对象。它就称之为原型对象,不管你是否打算将这个函数作为构造函数来用。那问题来了,为啥我们要关注prototype属性呢?

    1.原生构造函数(如 Object()/Array()/Function()等)使用prototype属性,以便让构造函数实力继承属性和方法。

    2.当用户自定义构造函数时,可以像javascript原生对象那样使用继承。

    3.可以借用别人编写的优秀代码的时候继承赋值过来自己用

    4.通过使用原型继承,我们可以创建有效的对象实例,并且使用相同的方法,这样就节省了很多代码。

    结束语

    本节重点是函数是对象,所表现出来的一些特性,同时函数作用域链相关的闭包这4个例子应该是堪称经典了,以后可以经常看看,还有比较重要的作用域链等等,以后再深入了解,再继续分享。同时如果有错误,还请指出。今天看了乐嘉书中,觉得有一句话说的挺好的,我全力回顾了自己曾有的梦想,对比已实现的和没实现的,终于发现,梦想都与行动有关,不动就是幻想,动了就是梦想,动到底梦想就实现了。也许我做的梦,刚好也是你的梦,果真如此,此刻开始,你我就算是同梦中人了。如果你觉得对你有所帮助,推荐一下,给我下次写作的动力。

    ps: 给大家介绍一个新词(不要问我是谁,请叫我好人)。

      路见不平   

      旧意:指走在路上遇见不公平的事情   

      新意:指走在路上在一大波平胸妹子中发现一个大波妹子   

      例句:路见不平,拔屌想护

  • 相关阅读:
    17. Letter Combinations of a Phone Number
    16. 3Sum Closest
    15. 3Sum
    14. Longest Common Prefix
    13. Roman to Integer
    12. Integer to Roman
    11. Container With Most Water
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
  • 原文地址:https://www.cnblogs.com/miniyk/p/3815223.html
Copyright © 2011-2022 走看看