• 对js中Function的浅见


    它到底是什么

    String Array 都是系统内置对象(已经定义好,可以直接使用)当然,这货也是一样,我们之前定义的函数,其实就是一个这货的实例。

    JS中,所有的对象都是由函数实现的,函数的数据类型是objectSo,我们以前定义的函数也是一个对象。

    几种写法

     1  function fn1(a,b){
     2   return a+b;
     3  }
     4 
     5   //前面表示参数,后面表示函数语句
     6   var fn2 = new Function("a","b","return a+b");
     7 
     8   // 匿名函数
     9   var fn3=function(a,b){
    10     return a+b;
    11   }
    12 
    13 
    14   console.log(fn1(1,2));
    15   console.log(fn2(1,2));
    16   console.log(fn3(1,2));    // 注意,一定要在声明函数的后面调用

    另外,如果函数没有明确的返回值,或者调用了没有参数的return,那么它真正返回的值是undefined

     1 function fn(){
     2   //.....
     3 }
     4 
     5 
     6 function fn1(){
     7   return;
     8 }
     9 
    10 
    11 console.log(fn()===undefined);  // true
    12 console.log(fn1()===undefined); // true

    arguments  

    arguments只有在代码运行的时候才起作用,它是一个数组(准确的说是伪数组),保存函数的参数。

     1 function fn(){
     2     var sum=0;
     3     for(var i=0;i<arguments.length;i++){
     4         sum+=arguments[i];
     5     }
     6     return sum;
     7   }
     8 
     9   var sum = fn(1,2);
    10   var sum2 = fn(1,2,3);
    11   console.log(sum);      // 3
    12   console.log(sum2);     // 6
    13 
    14   function fn1(a,b,c,d){
    15       console.log(arguments.length);
    16       console.log(arguments[0]);
    17   }
    18 
    19   fn1();                    //  0 、  undefined
    20   fn1(1);                   //  1 、 1
    21   fn1('a',2);               //  2 、 a
    22   fn1('李志',2,3);          //  3 、 李志
    23   fn1('李B',2,2,3,4,4);     //  6 、 李B

    Length

    我们需要了解两个东东,形参与实参(不同的资料书籍可能叫法有所差异)

    形参:函数定义的时候的参数  实参:调用函数的时候传递的参数

    length指的是形参个数   arguments.length指的是实参个数

    1  function fn(a, b) {
    2     console.log(fn.length);
    3     console.log(arguments.length);
    4  }
    5 
    6 fn(1, 2);  // 2   2
    7 fn(1);     // 2   1

    call  apply

    1,借用另一个对象的方法  2,替换this指向

    Apply方法  调用函数,并用指定对象替换函数的this值,同时用指定数组替换函数的参数。

    Call方法    调用一个对象的方法,用另一个对象替换当前对象。

     1     //对象1
     2     var obj1={
     3         getAllStudentsNumbers:function(sum,sum1){
     4             return sum+sum1}
     5     };
     6 
     7     //对象2
     8     var obj2={
     9         getDetail:function(){
    10             return {name:'阿拉三',age:'18'}
    11         }
    12     };
    13     console.log(obj1.getAllStudentsNumbers.call(obj2,10,200));      // 210
    14     console.log(obj1.getAllStudentsNumbers.apply(obj2,[10,200]));   // 210

    Function.apply(obj,args)方法能接收两个参数
    obj:这个对象将代替Function类里this对象
    args:这个是数组,它将作为参数传给Functionargs-->arguments

    我们通过如下方式将其转换成数组

    1 /* slice : 截取数组,返回的还是数组,这里我们截取全部  */
    2 var divs = document.getElementsByTagName("div")
    3 var domNodes =  Array.prototype.slice.call(divs);

    还可以实现继承,在上篇文章中说过,这里不做赘述。

    caller callee

    caller属性 获取调用当前函数的函数。caller属性只有当函数正在执行时才被定义。

    返回函数调用者,主要用于察看函数本身被哪个函数调用.

     1     function fn() {
     2         //判断某函数是否被调用
     3         if (fn.caller) {
     4             alert(fn.caller.toString());
     5         } else {
     6             alert("函数直接执行");
     7         }
     8     }
     9 
    10     function fn1() {
    11         fn();
    12     }
    13     fn1();
    14     fn();

    callee属性 返回正被执行的 Function 对象,即指定的Function 对象的正文。

    如下是一个递归算法 计算 1+2+3+4+...+n

    什么是递归?    可以这样理解,一个方法,自己调用自己,用上一次调用得出的结果作为这次的参数。

    传统方式的缺点:

    1、破坏了,零重复法则,当一旦函数名称更改,需要更改多处

    2、fn是一个全局变量,fn内部一般使用局部变量,而这里是一个全局变量,这是一个潜在的全局变量污染

    1 var fn=function(n){
    2     return n>0 ? n+fn(n-1) : 0;
    3 }
    4 console.log('采用传统方式:'+fn(10));

    优点:这样就让代码更加简练。又防止了全局变量的污染

    1 var fn=(function(n){
    2     return  n>0 ? n+arguments.callee(n-1) : 0;
    3 })(10);
    4 console.log('采用callee方式: '+fn);

    constructor prototype

    constructor属性,就是用来构造对象实例的函数引用。

    prototype属性,获取对象的原型。

    每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。

     contructorprototype属性是系统自动生成的。但本质上只是是函数对象的属性而已。

    对象是一个函数,而函数对象含有contructorprototype等属性,

    那么实例化的过程就是拷贝构造函数属性的过程,所以每个实例自然就拥有了contructorprototype这两个属性。

    自定义对象:函数实现的--函数又是Function的一个实例,所以这个自定义对象含有Function对象的一切属性和方法

    1 var product = function(){}
    2 /*自动有一个 prototype属性 它是一个对象--- 原型对象*/
    3 /* product.prototype也是对象,对象都是函数实现的,这货也包含Function对象的一切属性和方法,所以他也有。*/
    4 product.prototype.buy=function(){}
    5 product.prototype={}

    bind  

    Bind方法,创建具有与原始函数相同的主体的绑定函数。 在绑定功能中,this对象解析为传入的对象。 该绑定函数具有指定的初始参数。

    为了能在改变了上下文之后继续引用到this,大家通常选择使用self that _this 等方式先保存起来。这是完全可以的,现在有了bind:

     

     1 var obj={
     2       fn1:function(){
     3         console.log(1);
     4       },
     5       fn2:function(){
     6         console.log(2);
     7       },
     8       fn3:function(fn){
     9         fn();
    10         console.log(3);
    11       },
    12       fn4:function(){
    13         // var that=this;           // 还保存吗?
    14         // this.fn3(function(){
    15         //   console.log(4);
    16         //   that.fn1();
    17         //   that.fn2();
    18         // });
    19         this.fn3(function(){
    20           console.log(4);
    21           this.fn1();
    22           this.fn2();
    23         }.bind(this));        //  咦,发生什么?
    24       },
    25     }
    26     obj.fn4();

    再看一眼:

    1  var foo={
    2       x:3,
    3     }
    4     var bar=function(){
    5       console.log(this.x);
    6     }
    7     bar();
    8     var boundFunc=bar.bind(foo);
    9     boundFunc();

    想到了什么?call? apply? 没错,看下面三者的区别:

    1 fn1.hello.call(fn2,1,2,3);
    2 fn1.hello.apply(fn2,[1,2,3]);
    3 fn1.hello.bind(fn2)(1,2,3);

    好消息是,IE8以下并不支持。肿么办?  

    没关系,大牛们写好了,我们来看一下

     1 if (!Function.prototype.bind) {
     2         Function.prototype.bind = function (oThis) {
     3           if (typeof this !== "function") {
     4             throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
     5           }
     6         var aArgs = Array.prototype.slice.call(arguments, 1),
     7           fToBind = this,
     8           fNOP = function () {},
     9           fBound = function () {
    10             return fToBind.apply(this instanceof fNOP  ? this : oThis || this ,
    11                                  aArgs.concat(Array.prototype.slice.call(arguments)));
    12           };
    13           fNOP.prototype = this.prototype;
    14           fBound.prototype = new fNOP();
    15           return fBound;
    16 
    17         };
    18       }

    最后:

    JS中,函数的使用是非常之灵活,比如闭包、立即函数、等等等等,以后有机会专门讨论。

  • 相关阅读:
    CSS实现底部固定
    ES6新特性--多行文本
    DataTable转实体
    jQuery插件开发
    页面可编辑
    clearfix--清除浮动
    前端日历控件推荐
    图片Base64编码
    第八周学习进度博客
    人月神话多后感01
  • 原文地址:https://www.cnblogs.com/luqin/p/5221911.html
Copyright © 2020-2023  润新知