• 自我学习而已——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返回的结果是不一致的

  • 相关阅读:
    java 泛型
    数据结构与算法分析java——线性表1
    常见链表题
    网络面试题集锦
    java 网络流 TCP/UDP
    java文件
    java IO流——字节流
    java IO流——字符流
    java集合框架——工具类
    java集合框架——Map
  • 原文地址:https://www.cnblogs.com/yansi/p/3197984.html
Copyright © 2020-2023  润新知