zoukankan      html  css  js  c++  java
  • JavaScript笔记——基础知识(二)

    Function类型

    函数function不需要返回类型(不是没有返回值),参数也不需要指定类型,更为特殊的是函数竟然是个类,可以通过new出来

    var box= new Function('num1', 'num2' ,'return num1 + num2');

    这样的写法是完全正确的,但不推荐使用,因为会解析两次(第一次解析JavaScript代码,第二次解析参数)造成性能问题

    function可以当做参数使用

    很怪异,方法作为参数, 可以理解成把函数的引用作为参数)

    function box(sumFunction,num){            //将函数作为参数使用
        return sumFunction(num);
    }
    
    function sum(num){
        return num+10;                        //需要返回
    }
    
    alert(box(sum,10));

    函数内部属性

    在函数内部,有两个特殊的对象:argumentsthis

    arguments 是一个类数组对象,包 含着传入函数中的所有参数,主要用途是保存函数参数。但这个对象还有一个名叫 callee 的 属性,该属性是一个指针,指向拥有这个 arguments 对象的函数

    一个递归方法(可以使用arguments.callee方法代替调用本身)

    function box(num){
        if(num<=1){
            return 1;
        }else{
            //return num*box(num-1);
    return num*arguments.callee(num-1); } } alert(box(
    3));

    函数内部另一个特殊对象是 this,其行为与 Java 中的 this 大致相似。this 引用的是函数据以执行操作的对象,或者说函数调用语句所处的那个作用域,当在全局作用域中调用函数时,this 对象引用的就是 window

    var color='红色的';             //作用域
    alert(this.color);
    var box={
        color:'蓝色的',
        sayColor:function(){
            alert(this.color);
        }
    };
    box.sayColor();

    第一个this引用的是全局window,而第二个this引用的是box本身这个对象

    函数属性和方法

    JavaScript中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性: length prototype

    length 属性表示函数希望接收的命名参数的个数

    function box(name, age) {
    alert(name + age);
    }
    alert(box.length); //2

     prototype 属性,它是保存所有实例方法的真正所在,也就是原型。 prototype 下有两个方法:apply() call(),每个函数都包含这两个非继承而来的方法。这两个方法的用途都在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值

    apply()方法:

    function box(num1,num2){
        return num1+num2;
    }
    
    function sayBox(num1,num2){
        return box.apply(this,[num1,num2]);        //第二个参数是数组
    }
    
    function sayBox2(num1,num2){
        return box.apply(this,arguments);      //可以使用arguments替代参数列表
    }
    
    alert(sayBox2(10,10));

    call()方法:

    function box(num1,num2){
        return num1+num2;
    }
    
    function sayBox(num1,num2){
        return box.call(this,num1,num2);               //使用call方法传值不可以使用arguments
    }
    
    alert(sayBox(10,10));

    call()方法于 apply()方法相同,他们的区别仅仅在于接收参数的方式不同。对于 call()方法而言,第一个参数是作用域,没有变化,变化的只是参数传递的方式

    但事实上,传递参数并不是 apply()和 call()方法真正的用武之地;它们经常使用的地方是能够扩展函数赖以运行的作用域(对象冒充)

    var color='红色的';
    var box={
        color:'蓝色的'
    };
    function sayColor(){
        alert(this.color);
    }
    sayColor.call(this);                 //红色的
    sayColor.call(window);               //蓝色的
    sayColor.call(box);                  //apply和call方法的真正作用在于使对象和对象里的方法解耦合

    变量与作用域

    JavaScript 变量可能包含两种不同的数据类型的值:基本类型值和引用类型值。基本类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。 而引用类型值则是指那些保存在堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象(和Java的处理方式类似)

    变量

    对于变量类型和操作上和其他语言没有太大的差别,但需要注意基本类型和引用类型赋值操作的不同

    //基本类型
    var box='lee';                
    var box2=box;         //不同的,相互独立的两个空间
    box='alert';          //改变不会相互影响
    alert(box);
    alert(box2);
    
    //引用类型
    var box={
        name:'lee'
    };                
    var box2=box;         //不同的空间,相同的内容(同一个引用地址)
    box.name='alert';      //改变会相互影响
    alert(box.name);
    alert(box2.name);

    事实上Java中的类型也是这样操作的

    可以检测变量类型,使用typeof或instanceof

    var arr=[1,2,3];
    //alert(typeof arr);                   //typeof检测引用类型会出现 数组,对象,null都是object的问题,具体类型不知道
    alert(arr instanceof Array);          //使用instanceof检测引用类型
    
    
    var box='lz';
    //var box=new String('lz');
    alert(box instanceof String);             //但是instanceof检测基本类型会返回false.在这里如果String是new出来的,也会返回true 
    //alert(typeof box);                          //建议对基本类型的检测使用typeof ,对应用类型检测使用instanceof
    //Java也用instanceof检测类型,用法一致,但没有typeof

    作用域

    作用范围上其实与其他语言挺不同的,判断和循环语句的花括号竟然不能限定作用域

    if(true){                  //判断语句的花括号没办法限定其中值得作用域
        var i=10;
    }
    alert(i);                //10
    
    for(var i=0;i<10;i++){           //循环语句的花括号也没办法限定其中值得作用域
        var box='lz';
    }
    alert(i);                        //10
    alert(box);                      //lz
    
    function box(){            //只有function函数的花括号可以限定作用域
        var i=10;
    }
    alert(i);                 //报错

    还有就是this在全局的范围代表的window对象

    var color='红色的';             //作用域
    alert(this.color);
    var box={
        color:'蓝色的',
        sayColor:function(){
            alert(this.color);
        }
    };
    box.sayColor();
    alert(this.color);        //红色的   等同于alert(window.color); 

    传递参数

    JavaScript中所有函数的参数都是按值传递的,参数不会按引用传递,虽然变量有基本类型和引用类型之分,其实C++,java都是按值传递的,PHP是两种方式都有

    function box(num) { //按值传递,传递的参数是基本类型
    num += 10; //这里的 num 是局部变量,全局无效
    return num;
    }
    var num = 50;
    var result = box(num);
    alert(result); //60
    alert(num); //50

    以上的代码中,传递的参数是一个基本类型的值。而函数里的 num 是一个局部变 量,和外面的 num 没有任何联系

    容易混淆的是下面的代码

    function box(obj) { //按值传递,传递的参数是引用类型
    obj.name = 'lz';
    }
    var p = new Object();
    box(p);
    alert(p.name);            //lz

    结果改变了,这是因为我们按值传递一个地址的引用(可以这样理解),然而存在了不同空间,相同的内容(同一个引用地址),就会相互影响

    包装类

    为了便于操作基本类型值,JavaScript提供了 3 个特殊的引用类型:Boolean、Number 和 String。这些类型与其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。 实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象, 从而能够调用一些方法来操作这些数据,所以才可以向下面一样操作:

    //var str='Mr.li';
    //alert(str.substring(2));
    alert('Mr.li'.substring(2));        //根据指定位置向后截取

    这三个包装类提供了丰富的方法和属性来操作它们对应的基本类型,这里不一一记录了

  • 相关阅读:
    Razor 视图
    可选参数和命名参数
    CPU性能分析工具原理
    从硬件到语言,详解C++的内存对齐(memory alignment)
    谈谈C++的volatile关键字以及常见的误解
    C++11的value category(值类别)以及move semantics(移动语义)
    C++基于范围循环(range-based for loop)的陷阱
    C++模板入门教程(一)——模板概念与基本语法
    自己动手实现深度学习框架-8 RNN文本分类和文本生成模型
    自己动手实现深度学习框架-7 RNN层--GRU, LSTM
  • 原文地址:https://www.cnblogs.com/lz2017/p/6775458.html
Copyright © 2011-2022 走看看