美文网首页
javascript基础语法学习

javascript基础语法学习

作者: dounine | 来源:发表于2019-02-20 14:04 被阅读0次

    前言

    这是一次简单的JavaScript基础语法的重新学习,只记录JavaScript与C\C++的不同之处,相同的不再赘述。

    一、输出

    • 使用 window.alert() 弹出警告框。

    • 使用 document.write() 方法将内容写到 HTML 文档中。

    • 使用 innerHTML 写入到 HTML 元素。

    • 使用 console.log() 写入到浏览器的控制台。(常用)

    二、变量

    1.声明

    • var namevar num = 1。 不用说明变量的类型,编译器会自行判断。若初始化,则是初始化值的类型;若未初始化,则是undefined数据类型。每当该变量再次被赋值或再次被声明定义时,会被转换成新的数据类型。

    • let name。 声明的是块级作用域变量,只在块级作用域内有效,不能被块外部访问,且不可重名。块级指{....}之内的内容,如for{}中。

    • const name = 'jek'。 声明常量,块级作用域,必须初始化,不可修改。

    后两种声明方式为ES6特性。

    练习代码:

    //----------var、let、const声明变量-------------
      // var声明变量后,赋不同类型的值和重新声明定义
      var v1 = 1;
      console.log(v1, typeof v1);
      v1 = 'ssss';
      console.log(v1, typeof v1);
      var v1 = false;
      console.log(v1, typeof v1);
    
      // 函数局部
      function myFunction() {
        // var局部变量,外部可访问,但不能访问到局部变量的值。按理来说局部是不可访问的,此处笔者也很迷惑
        var name = 'bbbb';  
      }
      console.log(name, typeof name);   // 输出 空字符 + string
    
      // 块级区域
      for (var i = 0; i < 5; i++) {
        var x = i;      // var声明块级变量,外部可以访问且值相同
      }
      console.log(x);
    
      for (var i = 0; i < 5; i++) {
        let y = i;      // let声明块级变量,外部不可访问
      }
      console.log(y);
    

    输出结果:

    1 "number"
    ssss string
    false "boolean"
     string
    4
    Uncaught ReferenceError: y is not defined
    

    (注:js有变量提升的特性,即允许先使用(如赋值)再声明,但不建议使用)

    2.数据类型(6种值类型+3种引用类型)/(6种原始类型+对象类型)

    1)string

    字符串:var str = 'hello'。 可以用双引号或单引号包裹,如"hello"'hello'都可以(建议用单引号)。可以通过下标访问字符串中的字符。

    两个字符串之间可以通过 + 拼接。

    ES6中新增了字符串模板的特性。字符串需用``包裹起来,字符串中需要替换的变量用${}包裹。示例:

    var name="zzw";
    console.log(`hello ${name}`);
    

    输出hello zzw

    2)number

    数字:var num = 1。 包括整数、浮点数、科学计数法表示的数(2.1e10)。js中浮点数的精度是个问题。数字可以与字符串通过 + 拼接,此时数字会被转换成字符串。

    3)boolean

    布尔类型:var bo = true

    4)undefined

    无定义类型:var name。 变量声明时没有被定义,或者输出一个未声明的变量,则为undefined类型。

    5)null

    空类型:var name = nullname = null。 用来将变量置空,其实表示一个空对象引用。

    6)symbol

    symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。

    7)array

    数组:var arr = [1,2,3]或者var arr = new Array(1,2,3)。 在js中数组类型其实算作一种对象类型。 而且,js数组与C数组还有几个不同点:

    • js数组的每一项可以用来保存任何类型的数据,也就是说,可以用数组的第一个位置来保存字符串,第二个位置保存数值,第三个位置保存对象。
    • 数组的大小是可以动态调整的。
    • 访问超限时,输出undefined。
    8)function

    函数。在js中,函数也可以是变量,后面详细介绍。

    9)object

    对象。也算变量,后面再详细介绍。

    练习代码:

    //----------变量------------
      // number类型
      var num = 3;
      console.log(num, typeof num);
    
      // string类型
      var str = 'hello';
      console.log(str, typeof str);
    
      // 拼接字符串和数字
      console.log(str+' '+num);
    
      // boolean类型
      var bo = true;
      console.log(bo, typeof bo);
    
      // undefined类型
      var udf;
      console.log(udf, typeof udf);
    
      // null类型
      var nu = null;
      console.log(nu, typeof nu);
    
      // 数组
      var arr = [1,2,3];
      // var arr = new Array(1,2,3);
      console.log(arr, typeof arr);
      console.log(arr[9]);  // 访问超限,输出undefined
      arr = [1, 'hello', [2, 3]];
      console.log(arr, typeof arr);
    
      // 函数类型
      var fun = function() {
        console.log('this is a function');
      }
      console.log(fun, typeof fun);
    
      // 对象类型
      var obj = {
        name: 'tomcat',
        getName: function() {
          return name;
        }
      };
      console.log(obj, typeof obj);
    

    输出结果:

    3 "number"
    hello string
    hello 3
    true "boolean"
    undefined "undefined"
    null "object"
    [1, 2, 3] "object"
    undefined
    [1, "hello", Array(2)] "object"
    ƒ () {
            console.log('this is a function');
        } "function"
    {name: "tomcat", getName: ƒ} "object"
    

    三、运算符

    特别注意:在js中有相等==和绝对相等===,不相等!=和不绝对相等!==。区分如下:

    • ==。 值相等,类型可以不相等
    • ===。 值和类型都必须相等
    • !=。 ==取反,即类型相等时,值不相等
    • !==。 ===取反,即值或类型都可以不相等

    其它运算符与c的相同。

    四、语句

    if、for、while、switch等,与c相同。

    五、函数(重要)

    1.函数定义

    1)函数语句定义(常规)

    参数,可有可无,不用指定数据类型(js中,变量本就不需指定类型),默认为undefined类型。传入参数个数不定,按顺序未传入的参数为undefined。ES6中参数可以设定默认值。

    返回值,可有可无。

    function funA (a, b) {
        console.log('a is ' + a);
        console.log('b is ' + b);
        console.log('a+b is ' + (a+b));
    }
    funA(2, 4);
    funA(2);
    
    // ES6 函数参数可以设定默认值
    function funB (a, b = 10) {
        console.log('默认值 || ' + (a+b));
    }
    funB(3);
    

    输出:

    a is 2
    b is 4
    a+b is 6
    a is 2
    b is undefined
    a+b is NaN
    默认值 || 13
    
    2)函数表达式(函数变量)定义

    将匿名函数赋给一个变量,该变量可以跟函数一样使用,其数据类型为函数类型。

    var vB = function (a, b) {
        return a*b;
    };
    vB(2, 3);
    

    在《JavaScript权威指南》中说:

    以表达式定义的函数只适用于它作为一个大的表达式的一部分。

    其实,我觉得表达式定义形式也可以用于一般函数。感觉两者没什么太大区别,可能也是我不了解js的内部实现。

    2.匿名函数

    不带函数名的函数,即为匿名函数,如:

    function () {
        console.log('this is an anonymous function');
    }
    

    可单单定义一个匿名函数是无法调用的,因为它没有名字。但,我们可以通过将匿名函数赋给变量(该变量成为函数类型变量),或函数自调用的方式,来调用匿名函数。

    ES6新增用箭头函数来表示匿名函数:

    // ES6 新增箭头函数来表示匿名函数,一个参数时可以省略圆括号,一条语句可以省略花括号
    var vB = (a, b) => {
        console.log('箭头函数 || a-b is ' + (a-b));
    };
    vB(6, 3);
    

    3.函数自调用

    其形式为 (...匿名函数定义...)(...参数...); 。作用是在函数定义后立即调用该函数:

    (function (a, b) {
        console.log('函数自调用 || a-b is ' + (a-b));
    })(6, 2);
    

    ((a, b) => {
        console.log('箭头函数 || a-b is ' + (a-b));
    })(6, 2);
    

    输出:

    函数自调用 || a-b is 4
    箭头函数 || a-b is 4
    

    4.函数作为值

    在js中,函数也是变量,那么函数就可以当作一个变量来进行传递。

    1)函数作为返回值(函数闭包)

    函数返回一个子函数(嵌套函数),那接受这个返回值的变量即是函数类型变量。

    function fa (first) {
        return function (second) {
            return first += second;
        };
    }
    var son = fa(0);    // son变量接受一个返回函数
    /*相当于
    var son = function (second) {
        return first += second
    };
    只是这样定义时,不能使用函数fa()的局部变量first
    */
    console.log(son(1));    // 输出 1
    console.log(son(1));    // 输出 2
    

    function fa (first) {
        return (second) => {
            return first += second;
        };
    }
    var son = fa(0);
    console.log(son(1));
    console.log(son(1));
    

    // 直接将fa函数写成自调用的匿名函数,自调用后返回一个函数给son变量
    var son = (((first) => {
        return (second) => {
            return first += second;
        };
    })(0));
    console.log(son(1));
    console.log(son(1));
    

    输出:

    1
    2
    

    从第一个代码示例中,我们可以发现:返回一个函数(fa)的内部函数(son)时,我们可以通过这个返回的函数(son)来使用外函数(fa)中的局部变量。而且在不断调用内部函数(son)的过程中,外函数(fa)并没有被销毁(出栈)。由于这种机制,我们就可以让函数拥有私有变量,不能被全局使用,但又可以一直保持值不被销毁。而这就是闭包

    代码:

    //函数闭包。使函数可以拥有私有变量(外部不可访问,同时也不会因为函数调用而刷新)
    var add = (() => {
        var counter = 0;
        return () => {return counter += 1;}
    })();
    add();  // add()实际调用的是上述匿名主函数中返回的匿名子函数
    add();
    add();
    console.log('函数闭包 || ', add());
    

    输出:

    函数闭包 ||  4
    
    2)函数作为参数(多态性/Lambda表达式)

    将一个自定义函数作为参数传入另一个函数中,这个传入函数可以根据不同情况自行定义,从而让被传入函数实现不同效果。

    // 函数作为参数。使多态性得以体现
    function appendDiv (callback) {
        for(var i=0;i<10;i++){
            var div = document.createElement('div');
            div.innerHTML = i;
            document.body.appendChild(div);
            // 如果传入的参数是一个函数类型的变量
            if(typeof callback == 'function'){
                callback(div);      // 将该形参作为函数变量使用
                console.log(callback);
            }
        }
    }
    // 将一个自定义的匿名函数作为参数传入appendDiv()函数
    appendDiv((node) => {
        node.style.display='block';     // 让该元素以块元素展示(独占一行)
    });
    appendDiv((node) => {
        node.style.display='inline';    // 让该元素以行内元素展示
    });
    

    显示结果:


    函数作为参数.png

    函数作为参数传入另一个函数的方式,常用于将自定义的回调函数传入接口函数中。但,在传入自定义参数到接口函数的这种场景中,常常是将回调函数作为对象中的一个方法传入的。

    如微信小程序开发中常用的网络请求接口函数:

    wx.request({
      url: wx.getStorageSync('requestUrl') + '/small/config',
      method: 'GET',
      data: {
      },
      header: {
        'content-type': 'application/json'
      },
      success: (res) => {
        console.log('get config: ', res.data.WeCosUrl)
        wx.setStorageSync('wecosUrl', res.data.WeCosUrl)
      }
    });
    

    wx.request()是微信提供的用于网络请求的接口函数,其参数是一个对象。对象中的success方法,是wx.request()函数执行访问成功后调用的函数,由用户自定义。而这就是一种多态性。

    六、对象(重要)

    1.js中的对象

    在js中,大部分事物都是一个对象。引用《JavaScript权威指南》中的话说:

    除了字符串、数字、true、false、null和undefined之外,JavaScript中的值都是对象。尽管字符串、数组和布尔值不是对象,但它们的行为和不可变对象非常类似。

    字符串有对象的部分特性,如:

    var message='Hello World!';
    console.log(message.length);    // 获取字符串的长度属性
    

    但,字符串“对象”的属性是不可修改的,如修改message.length的大小是无效的。同时,字符串还有很多常用的自带方法,如:内容匹配match()、内容替换replace()、转换大小写toUpperCase()/toLowerCase()等等。

    2.对象创建

    js中,对象用{...}将属性和方法包裹起来。每个属性和方法都有唯一的名字,而且名字和值之间是通过:一一映射的。如:

    var obj = {
      name: 'tomcat',
      getName: function() {
        return this.name;
      }
    };
    console.log(obj.getName()); // 输出 tomcat
    

    this的注意点

    this关键字指向的是调用该函数的对象。如果不使用this.name,可能会返回全局中的name变量。如:

    var obj = {
      name: 'tomcat',
      getName: function() {
        return name;
      }
    };
    var name = 'tom';
    console.log(obj.getName()); // 输出 tom
    

    另外,箭头函数虽然是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:this指针的指向。匿名函数中this指向调用者对象,而箭头函数中的this指向再上一层调用者对象。如:

    var name = 'tom';
    var obj = {
        name: 'tomcat',
        getName: () => {
            console.log(this);  // 输出 window对象
            // 由于箭头函数,this指针指向上一层对象,即全局对象,因此这里的this.name是全局中的name变量
            return this.name;   
        }
    };
    console.log(obj.getName()); // 输出 tom
    

    所以,在对象的方法定义中,不建议使用箭头函数


    对象还可以通过new + 构造函数的方法来创建,如:

    var o = new Object(); // Object()是Object这个js“原型”对象的构造函数。返回一个空对象
    

    3.js对象属性和方法的动态性

    可以动态增加与删除对象中的属性和方法,如:

    // 动态增加属性 方法
    var book = {};
    // var book = new Object();
    book.author = 'es6';
    book.title = 'JavaScript';
    book.changeTitle = function () {
        this.title = 'python';
        return this.title;
    };
    console.log(book.author, book.title, book.changeTitle());   // 输出 es6 JavaScript python
    
    // 删除属性、方法
    delete book.author;
    console.log(book.author); // 输出 undefined
    

    4. js对象的引用与赋值

    js中对象值是引用类型,相当于指针。

    // 对象的引用与赋值
    var obj1 = {
      a : 1
    }
    var obj2 = obj1;
    obj2.a = 2;
    console.log(obj1.a);  // 输出2
    

    var obj2 = obj1;相当于把obj1的指针赋给obj2,所以obj1obj2指向同一对象的数据。

    同时,若函数参数为对象,并在函数中修改对象中数据,那也会影响到函数外的对象。

    那js应该如何正确的进行对象赋值呢,代码如下:

    // 对象间赋值的正确方法
    var obj3 = {
      a:1,
      b:2,
      c:3,
      d:[0,1,2,3]
    };
    var jsonStr = JSON.stringify(obj3);
    var obj4 = JSON.parse(jsonStr);
    obj4["e"] = 4;
    obj4["d"][0] = 11;
    console.log(obj3);  //Object {a: 1, b: 2, c: 3, d: [0,1,2,3]}
    console.log(obj4);  //Object {a: 1, b: 2, c: 3, d: [11,1,2,3], e: 4}
    

    相关文章

      网友评论

          本文标题:javascript基础语法学习

          本文链接:https://www.haomeiwen.com/subject/pchhyqtx.html