自我学习而已——javascript——Function类型和基本包装类型

  1.Function类型

    javascript所有的函数都只是Function类型的一个实例,函数是对象,函数名是指针,可以通过用Function()构造函数的方式创建函数,这样子效率很低,但是可以很直观的看到——函数只是个对象。所以,如果是函数名赋值为null,但是还有其他的指针指向这个函数的话,这个函数依旧不会被垃圾收集掉。

  2.函数声明和函数表达式

    浏览器的解析器在向执行环境中加载数据时,对函数表达式和函数声明不是一样对待的

 函数声明(可以先调用后声明):

        alert(sum(10, 10));
        function sum(num1,num2) {
            return num1 + num2;
        }
View Code

这样子写是没有问题的,虽然函数在执行之后声明,但是解析器会率先读取函数声明,并且使其在执行任何代码之前保证可以访问。所以即使先执行后声明函数都是没有问题的

  函数表达式(不能先调用后赋值)

    alert(sum(10, 10));
        var sum = function (num1, num2) {
            return num1 + num2;
        }
View Code

这种模式会在引用sum的时候就报错了,因为这时的sum是未定义状态,而且js也不会往下执行了。

  ps:还有一种区别就是函数表达式声明的函数实际上是一个匿名函数,其name属性是空值(或者是在某些ie下为未定义),var 后面变量的名字仅仅代表的是这个指针指向匿名函数,但是没有改变函数本身的性质

   3.通过arguments减少耦合

  函数都有一个arguments对象,这个对象是用来指函数的参数用的,但是,arguments对象有一个callee属性,是一个指针,指向这个arguments对象的函数(换句话说 arguments.callee()就等于调用这个方法)  

//            第一种模式,耦合紧密            
            function factorial2(num) {
                if (num <= 1) {
                    return 1;
                } else {
                    return num * factorial2(num-1);
                }
            }
            alert(factorial2(4));

//            第二种模式,耦合不紧密            
            function factorial1(num) {
                if (num <= 1) {
                    return 1;
                } else {
                    return num * arguments.callee(num - 1);
                }
            }
            alert(factorial1(6));
View Code

这里有2种方法,第一种方法的话就会使得耦合度很高,如果以后改了函数名字之后会导致在函数内部的名字也需要更改,而第二种就没有这个问题,可以改完之后直接使用

  4.通过call()和apply()来扩充函数作用域

  apply和call基本一样,就是你传入的参数有些不同

  通过call()扩充函数作用域  

            window.color="red";
            var o={color:"blue"};
            function sayColor(){
             alert(this.color);
            }
             
            sayColor.call(this) ;
            sayColor.call(window);
            sayColor.call(o);
View Code

  这样子的话就可以实现函数在指定的作用域下执行(改变这个函数内的this指针指向的位置)

  ps:我在很多地方看到的都是说 sayColor.call(this) ;是把sayColor执行的时候指针指向this,但是其实我的测试结果应该是sayColor的执行作用域被同步为“this所处于的作用域”,因为你把this换成任何对象或者对象属性(非对象)都是可以的;

   5.基本包装类型

  假如我们声明一个var s1="some text";的话,我们可以有s1.substring(2)这样的方法来切割字符串,但是s1是一个基本数据类型,不是一个对象,怎么会有方法呢?

  是这样的,实际上我们在调用substring方法的时候,创建了一个新的String对象的实例,这个实例调用制定的方法,然后这个实例被销毁掉

            var s1="some text";
             alert(typeof s1);
             s1=new String("some text");
             alert(typeof s1);
            var s2=s1.substring(2);
            s1=null;
            s1="some text";
View Code

可以看作是执行了这样的代码,而因为是自动创建的,生存周期只有执行这一行代码的短短时间。执行完了就被销毁了。所以不能给这样的对象添加属性和方法,就算添加了之后还是会被销毁

   所以

  1:即使js可以方便的给基本类型调用方法,但是基本类型不能添加属性和方法还是保留这个特性的。

   2:最好不要显式的声明String,Number,Boolean类型的数据,因为这样可能会造成误解,typeof和instanceof返回的结果是不一致的

原文地址:https://www.cnblogs.com/yansi/p/3197984.html