JavaScript基础(ECMA)

  • JavaScript简介:

    • JavaScript是一种解释执行的脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型,它遵循ECMAScript标准。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,主要用来给HTML增加动态功能。它是一种可以同时运行在前端与后端的语言。如Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境(类似Java或.NET)。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。

    • JavaScript脚本语言特点

      • a)、解释型的脚本语言。 JavaScript是一种解释型的脚本语言,C、C++等语言先编译后执行,而JavaScript是在程序的运行过程中逐行进行解释。基于对象。JavaScript是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象。

        b)、简单。JavaScript语言中采用的是弱类型的变量类型,对使用的数据类型未做出严格的要求,是基于Java基本语句和控制的脚本语言,其设计简单紧凑。

        c)、动态性。JavaScript是一种采用事件驱动的脚本语言,它不需要经过Web服务器就可以对用户的输入做出响应。在访问一个网页时,鼠 标在网页中进行鼠标点击或上下移、窗口移动等操作JavaScript都可直接对这些事件给出相应的响应。

        d)、跨平台性。JavaScript脚本语言不依赖于操作系统,仅需要浏览器的支持。因此一个JavaScript脚本在编写后可以带到任意机器上使用,前提上机器上的浏览器支 持JavaScript脚本语言,目前JavaScript已被大多数的浏览器所支持。

  • JavaScript组成:

    • ECMAScript(也就是今天的笔记Script基础) :描述了该语言的语法和基本对象,如类型、运算、流程控制、面向对象、异常等。也就是基础。
    • 文档对象模型(DOM):描述处理网页内容的方法和接口。(整合js,css,html)
    • 浏览器对象模型(BOM):描述与浏览器进行交互的方法和接口。(整合js和浏览器)
  • JavaScript引入方式:

    • script标签内:
      在head标签里面可以写,在body标签里面也可以写,放到head标签里面和放到body标签里面到底有什么区别,我们后续在讲~
      <script>
        // 在这里写你的JS代码
       //console.log('骑士计划!') #f12建打开浏览器的调试窗口,然后在console这个调试台就能看到这个内容了
        //alert('骑士计划!')  #这个是浏览器窗口一打开咱们这个文件,就弹出一个窗口
      </script>
      
      上面的代码运行后,我们看可以在浏览器的控制台查看都又相应的字
      

  • 引入外部的js文件:
    <script src="myscript.js"></script>
    
  • JavaScript语言规范

    • 注释
      // 这是单行注释
      
      /*
      这是
      多行注释
      */
      
    • 结束符:
      • JavaScript中的语句要以分号(😉 为结束符,且代码块用{}包含,也就是说和缩进没有干系。
    • 变量声明:
      1.JavaScript的变量名可以使用_,数字,字母,$组成,不能以数字开头。
      2.声明变量使用 var 变量名; 的格式来进行声明
      
      var name = "Alex";
      也可以分两步,声明变量var name;然后name='Alex',但是通常我们都是一步写完
      var age = 18;
      
      #注意
       变量名是区分大小写的。
        推荐使用驼峰式命名规则。首字母大写
        保留字不能用做变量名。
      
      补充:(ES6新特性,等咱们学到 VUE 在细说,简单了解一下就行了)
      ES6新增了let命令,用于声明变量。其用法类似于var,但是所声明的变量只在let命令所在的代码块内有效。例:
      for (let i=0;i<arr.length;i++){...}
      
      ES6新增const用来声明常量。一旦声明,其值就不能改变。这个东西就是为了定义一个固定的常量,供大家使用,这个常量不会改变
      const PI = 3.1415;
      PI // 3.1415
      
      PI = 3
      // TypeError: "PI" is read-only
      
  • JavaScript 数据类型

    • 在JS中使用var关键词声明变量,变量的类型会根据其所赋值来决定(动态类型)。JS中数据类型分为原始数据类型(5种)和引用数据类型(Object类型)。

      原始数据类型:Undefined、Null、Boolean、Number和String
      引用数据类型:Array、Object、Function 
      
  • typeof 运算符: 查看变量类型,对变量或调用typeof运算符将返回下列值之一:

     undefined – 如果变量是 Undefined 类型的
     
     boolean –   如果变量是 Boolean 类型的
     
     number  –   如果变量是 Number 类型的
     
     string  –   如果变量是 String 类型的
     
     object  –   如果变量是一种引用类型或 Null 类型的
     
     #示例:
    c = '123ss'
    typeof(c)  //"string"
    
  • 通过instanceof 运算符解决引用类型判断问题:

    #例1
    var oStringObject = new String("hello world"); 
    console.log(oStringObject instanceof String);   // 输出 "true"
    
    #例2 判断 foo 是否是 Foo 类的实例
    function Foo(){} 
    var foo = new Foo(); 
    console.log(foo instanceof Foo)//true
    
    #例3
    c instanceof String; //false
    
  • 原始数据类型和引用数据类型变量在内存中的存放如下:

  • JavaScript拥有动态类型(python也是动态的),也就是在之前并不说明对象的类型
    var x;  // 此时x是undefined  静态语言比如c:创建变量的时候,要指定变量的类型,python3.6也出现了类型注解的新特性def func(x:int,y:int) --> int: return x + y,意思是参数是int类型,返回值也是int类型的,就是个注释的作用
    var x = 1;  // 此时x是数字
    var x = "Alex"  // 此时x是字符串
    
    
  • 数值类型(Numberi)
    #JavaScript不区分整型和浮点型,就只有一种数字类型,NaN也是数字类型,当有东西要转为数值时,不符合要求就用NaN占位
    var a = 12.34;
    var b = 20;
    var c = 123e5;  // 12300000
    var d = 123e-5;  // 0.00123
    
    #示例   Not a Number => NaN
    parseInt("123")  // 返回123
    parseInt("ABC")  // 返回NaN,NaN属性是代表非数字值的特殊值。该属性用于指示某个值不是数字。
    parseFloat("123.456")  // 返回123.456
    
    parseInt('qw');  //NaN
    
    
  • 字符串类型(String)
    var a = "Hello"
    var b = "world;
    var c = a + b; 
    console.log(c);  // 得到Helloworld
    
    
    • String对象属性

    • 字符串常用方法:

        方法	       说明
      .length        //不加括号的是属性	返回长度
      .trim()        //得到一个新值	     移除左右空白
      .trimLeft()	    //移除左边的空白
      .trimRight()	//移除右边的空白
      .big()          //用大号字体显示字符串。
      .charAt(n)     //n类似索引,从0开始,超过最大值返回''空字符串	  返回第n个字符
      .concat(value, ...)    //s='hello';s.concat('xx');得到helloxx	  拼接
      .indexOf(substring, start) //这个start是从索引几开始找,没有返回-1子序列位置
      .substring(from, to)    //不支持负数,所以一般都不用它,了解一下就行了根据索引获取子序列
      .substr()     //如果有两个参数,第二个参数表示切字符串的个数
      .slice(start, end)      //var s1='helloworld';s1.slice(0,-5)看结果,就用它	切片
      .toLowerCase()   //全部变小写	 小写
      .toUpperCase()   //全部变大写	 大写
      .split(delimiter, limit)  //分隔,s1.splite(' '),后面还可以加参数s1.split(' ',2),返回切割后的元素个数	分割
      .indexof()   //获取索引值
      .lastIndexof()  //获取最后一个字符的索引值
      
        es6的模板字符串
        ``  插入变量用${变量名}
      
      
      • 字符串应用

        ES6中引入了模板字符串。模板字符串(template string)是增强版的字符串,用反引号(``)标识,ESC键下面那个键就是反引号。它可以当做普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。你使用chorme浏览器就行,chorme浏览器支持ES6
        
        // 普通字符串
        `这是普通字符串!`
        // 多行文本
        `这是多行的文本`
        // 字符串中嵌入变量
        
        #字符串的占位
        var name = "q1mi", time = "today";
        `Hello ${name}, how are you ${time}?`  //"Hello q1mi, how are you today?"
        
        
        #字符串方法总结
        1、chartAt() 返回指定索引的位置的字符
        var str1 = 'al';
        var str2  = 'ex';
        console.log(str1.concat(str2,str2));  //alexex
        
        2、replace(a,b) 将字符串a替换成字符串b
          var a = '1234567755';
        var newStr = a.replace("4567","****");
          console.log(newStr);     //123****755
        
        3、indexof() 查找字符的下标,如果找到返回字符串的下标,找不到则返回-1 。跟seach()方法用法一样
          var str = 'alex';
          console.log(str.indexOf('e'));  //2
          console.log(str.indexOf('p'));   //-1
        
        4、slice(start,end) 左闭右开 分割字符串
          var str = '小马哥';
          console.log(str.slice(1,2));//马
        
          5、split('a',1) 以字符串a分割字符串,并返回新的数组。如果第二个参数没写,表示返回整个数组,如果定义了个数,则返回数组的最大长度
          var  str =  '我的天呢,a是嘛,你在说什么呢?a哈哈哈';
          console.log(str.split('a'));  //["我的天呢,", "是嘛,你在说什么呢?", "哈哈哈"]
        
          6、subStr(statr,end) 左闭右开
          var  str =  '我的天呢,a是嘛,你在说什么呢?a哈哈哈';
          console.log(str.substr(0,4));//我的天呢
        
          7、将number类型转换成字符串类型
          var num = 132.32522;
          var numStr = num.toString();
          console.log(typeof numStr);
        
          8、四舍五入
          var num = 132.32522;
          var newNum = num.toFixed(2);  //四舍五入,2表示保留2位
          console.log(newNum);
        
        
  • 布尔值(Boolean)
    • 区别于Python,true和false都是小写的。

      var a = true;
      var b = false;
      
      
    • ""(空字符串)、0、null、undefined、NaN都是false。
      • null     :表示值是空,一般在需要指定或清空一个变量时才会使用,如 name=null;
        undefined:表示当声明一个变量但未初始化时,该变量的默认值是undefined。还有就是函数无明确的返回值时,返回的也是undefined。
        null:表示变量的值是空,undefined:则表示只声明了变量,但还没有赋值。
        
        #没有返回值时
        function f(n1){console.log(n1);}
        var result=f(); //参数未赋值
        console.log(result);  //当函数没有返回值时为undefined
        
        #没有定义时
        var user = {
            name: "张学友",
            address: "中国香港"
        };
        console.log(user.age);  //访问对象中的属性,未定义
        
        #变量未赋值时
        var i;
        console.log(i);  //变量未赋值
        
        null 与 nudefined 的一些有趣特性:
            1、如果对值为 null 的变量使用 typeof 操作符的话,得到的结果是 object ;
            2、而对 undefined 的值使用 typeof,得到的结果是 undefined 
        typeof null === "object" //true; 
        typeof undefined === "undefined" //true 
        null == undefined //true
        
        
    • 对象(Object)
      • JavaScript 中的所有事物都是对象:字符串、数值、数组、函数...此外,JavaScript 允许自定义对象。JavaScript 提供多个内建对象,比如 Number、String、Date、Array 等等,通过new实例化的对象都是object类型(var s = new String('hello'),var n = new Number(12)等),数组不需要new生命,类型就是object类型。

      • 对象只是带有属性和方法的特殊数据类型。

      • 数组:使用单独的变量名来存储一系列的值。类似于Python中的列表。

        var a = [123, "ABC"]; 
        console.log(a[1]);  // 输出"ABC"
        
        var a = [123,'ss']
        typeof(a);  //"object"
        
        #常用方法
         方法	                      说明
        .length	                 //数组的大小
        // 栈方法 后进先出
        .push(ele)	             //尾部追加元素,类似于append
        .pop()	                  //获取尾部的元素,删除尾部
        // 堆方法 先进先出
        .unshift(ele)	          //头部插入元素
        .shift()	               //头部移除元素
        
        .slice(start, end)	       //切片
        .reverse()                 //在原数组上改的反转
        .join(seq)                 //a1.join('+'),seq是连接符	将数组元素连接成字符串
        .concat(val, ...)          //连个数组合并,得到一个新数组,原数组不变	连接数组,会生成新值
        .sort()  	               //排序
        .forEach()                 //讲了函数再说	将数组的每个元素传递给回调函数
        .splice()  //参数:1.从哪删(索引), 2.删几个  3.删除位置替换的新元素(可多个元素)删除元素,并向数组添加新元素。不会生成新值
        .map()           //讲了函数再说	返回一个数组元素调用函数处理后的值的新数组
        .toString( )	//将数组转换成一个字符串,用逗号隔开,要是不想用逗号隔开,就使用join
        
        //concat 合并数组
        var a = [123, "ABC"]; 
        c=a.concat([1,2]);
        console.log(c);  //[123, "ABC", 1, 2]
        
        //splice 删除与添加
        var a=[1,2,3,4,5];
        a.splice(1,3,'ok','nice','good');
        console.log(a);    //[1, "ok", "nice", "good", 5]
        
        //join 拼接字符
        var a = [1,2,3,4];
        c=a.join('*');
        console.log(c);   //1*2*3*4
        console.log(typeof(c))  //string,也就是说会将数字转化为字符进行拼接
        
        //slice截取
        var array51=[1,2,3,4,5,6];
        var array53=array51.slice(2);  //从第3个元素开始截取到最后
        console.log("被截取:"+array53+"——"+array51);   //被截取:3,4,5,6——1,2,3,4,5,6
        var array54=array51.slice(1,4);  //从第3个元素开始截取到索引号为3的元素
        console.log("被截取:"+array54+"——"+array51);   //被截取:2,3,4——1,2,3,4,5,6
        
        //sort 排序
          1、在sort中没有参数时,会将要排序的对象全部转化为字符串,并按照其对应的字符编码进行排序,如下
          var a=[11,2,12,19];
          a.sort();
          console.log(a);  //[11, 12, 19, 2] 这里先根据第一位进行排序,但不是我先看到的,怎么办?
        
          2、自定义函数,类似于python的sort对应的key,也就是自己提供一个函数提供排序规则,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:(sort会自动提供一个排序算法)
          
         //示例1
        function sortNumber(a,b) {return a-b}  //从小到大,反过来从大到小
        var arr=[11,12,19,2,23];
         arr.sort(sortNumber);
        console.log(arr);  //[2, 11, 12, 19, 23]
        
        //示例2
          var arr= [ 
            { 'sortNo': 2},
              { 'sortNo': 1},
              { 'sortNo': 5},
              { 'sortNo': 6},
              { 'sortNo': 7},
              { 'sortNo': 3},
              { 'sortNo': 9},
              { 'sortNo': 4},
              { 'sortNo': 0}
          ];
          arr.sort(function(a, b){
                  return a.sortNo - b.sortNo;
          });
        console.log(arr);  //会根据对应的值进行排序
        
        // 数组中遍列数组的量最重方法
        var a = [10,20,12,34];    
        for (var i=0; i<a.length; i++) { console.log(a[i])}  //方式一
          
        for (var i in a) {console.log(a[i])} //方式二
        
        //对象类型于字典
        var obj = {
            'name':'mjj';
            'age':12;
        }
        for(var key in obj){
            obj[key]
        }
        
        
      • forEach()

        语法: forEach(function(currentValue, index, arr), thisValue)
        
        #这里function必需的,currentValue	必需,当前元素;index	可选。当前元素的索引值。arr	可选。当前元素所属的数组对象。
        #thisValue	可选。传递给函数的值一般用 "this" 值。如果这个参数为空, "undefined" 会传递给 "this" 值
        
        - map()
        语法:map(function(currentValue,index,arr), thisValue)  //参数和上一直
        
        

    • 数组的增删改查

      #数组的创建
      var array11 = new Array();  //空数组
      var array12 = new Array(5);  //指定长度,可越界
      var array13 = new Array("a","b","c",1,2,3,true,false);  //定义并赋值
        
        #访问并修改
        array12[8]="hello array12";  //赋值或修改
        console.log(array12[8]);   //取值
        
        #添加元素:push、unshift、splice
        var array31=[5,8];
        //添加到末尾
        array31.push(9);
        var len=array31.push(10,11);
        console.log("长度为:"+len+"——"+array31);  //长度为:5——5,8,9,10,11
        //添加到开始
        array31.unshift(4);
        var len=array31.unshift(1,2,3);
        console.log("长度为:"+len+"——"+array31);   //长度为:9——1,2,3,4,5,8,9,10,11
        //添加到中间
        var len=array31.splice(5,1,6,7);  //从第5位开始插入,删除第5位后的1个元素,返回被删除元素
        console.log("被删除:"+len+"——"+array31);  //被删除:8——1,2,3,4,5,6,7,9,10,11
        
        #删除:pop、shift、splice
        var array41=[1,2,3,4,5,6,7,8];
        console.log("array41:"+array41);
        //删除最后一个元素,并返回
        var e=array41.pop();
        console.log("被删除:"+e+"——"+array41);
        //删除首部元素,并返回
        var e=array41.shift();
        console.log("被删除:"+e+"——"+array41);
        //删除指定位置与个数
        var e=array41.splice(1,4);  //从索引1开始删除4个
        console.log("被删除:"+e+"——"+array41);
      
      

内置对象和方法

  • JavaScript中的所有事物都是对象:字符串、数字、数组、日期,等等。在JavaScript中,对象是拥有属性和方法的数据。

    • 我们在学习基本数据类型的时候已经带大家了解了,JavaScript中的Number对象、String对象、Array对象等。

      注意var s1 = "abc"和var s2 = new String("abc")的区别:typeof s1 --> string而 typeof s2 --> Object

  • 自定义对象
    • JavaScript的对象(Object)本质上是键值对的集合(Hash结构),但是只能用字符串作为键。

      var a = {"name": "Alex", "age": 18};
      console.log(a.name);
      console.log(a["age"]);
      
      #遍历对象中的内容
      var a = {"name": "Alex", "age": 18};
      for (var i in a){
        console.log(i, a[i]);
      }
      
      #自定义对象,key可以不加引号时,取值方式有两种,里面的key要加引号,还可以通过点取值
      var a={name:'xxx'}
      console.log(a.name);    //xxx
      console.log(a['name']); //xxx   这时候需要加引号,即使你最开始没有加,否则未undefined
      
      var a={'name':'xxx'} //key加引号也一样
      console.log(a.name);    //xxx
      console.log(a['name']); //xxx
      
      

运算符

  • 算数运算符
    + - * / % ++ --  
    i++,是i自加1,i--是i自减1   i++的这个加1操作优先级低,先执行逻辑,然后再自加1(注意,在for循环中,在第二个参数条件执行完后才,i++)
    而++i,这个加1操作优先级高,先自加1,然后再执行代码后面的逻辑。
    
    
  • 比较运算符
    >大于  >=大于等于  <小于 <=小于等于 !=不等于  ==弱等  ===强等  !==强不等
    
    1 == “1”  // true  #弱等于,将1转换为字符串'1',在=号两个数据类型不同的时候,会自动给你变成相同的,具体怎么一个变换规则,先不用理他,因为这种比较不好,因为以后咱们就尽量用===。
    1 === "1"  // false #强等于,比较类型也比较值
    
    也就是说:
    ==  比较的是值
    === 比较的是值和数据类型
    
    
  • 逻辑运算符符
    && || !     //相当于and,or,非(取反)!null返回true
    
    
  • 赋值运算符
    =  +=  -=  *=  /=   //n += 1其实就是n = n + 1
    
    

流程控制

  • if - else
    var a = 10;
    if (a > 5){
      console.log("yes");
    }else {
      console.log("no");
    }
    
    
  • if - else if - else 多条件
    var a = 10;
    if (a > 5){
      console.log("a > 5");
    }else if (a < 5) {
      console.log("a < 5");
    }else {
      console.log("a = 5");
    }
    
    
  • switch 切换
    var day = new Date().getDay(); //示例化一个今天的日期对象,getDay()是获取天数的编号,0表示星期日
    switch (day) {  //这里day这个参数必须是一个值或者是一个能够得到一个值的算式才行,这个值和后面写的case后面的值逐个比较,满足其中一个就执行case对应的下面的语句,然后break,如果没有加break,还会继续往下判断
      case 0: //如果day是0
      console.log("Sunday"); //执行它
      break; //然后break跳出,如果没有break,则会进行后面的case
      case 1:
      console.log("Monday");
      break;
    default:  //如果没有任何满足条件的,就执行它
      console.log("...");
    }
    
    var i=1;
    switch (i){
        case 2:
        console.log('ok');
        break;
        case 1:
        console.log('nice');
        case 0:
        console.log('good');
        break;
        default:
            console.log('……');    
    }
    //nice  good
    
    
  • for循环
    for (var i=0;i<10;i++) {  //就这么个写法,声明一个变量,变量小于10,变量每次循环自增1,for(;;){console.log(i)};这种写法就是个死循环,会一直循环,直到你的浏览器崩了,就不工作了,回头可以拿别人的电脑试试~~
      console.log(i);
    }
    
    #循环数组:
    var l2 = ['aa','bb','dd','cc']
    方式1
    for (var i in l2){
       console.log(i,l2[i]);  //这里的i是索引值,不是取到的每一项
    }
    方式2
    for (var i=0;i<l2.length;i++){
      console.log(i,l2[i])
    }
    
    循环自定义对象:
    var d = {aa:'xxx',bb:'ss',name:'小明'};
    for (var i in d){
        console.log(i,d[i],d.i)  //注意循环自定义对象的时候,打印键对应的值,只能是对象[键]来取值,不能使用对象.键来取值。
    
    
  • while循环
    #方式一:条件在前
    var i = 0;
    while (i < 10) {
      console.log(i);
      i++;
    }
    
    #方式二:条件在后
    do{
        循环体
    }while(条件);
    
    //实例:
    do {
        //把用户输入的结果存储到result变量中
        var result = prompt("您觉得我帅吗?y/n");
    } while (result != "y");
    console.log("您真有眼光");
    
    #综合案例
    //三角形的五角星
    for (var i = 0; i <= 5; i++) {
        //控制每一行有几个星星
        for (var j = 0; j <= i; j++) {
            document.write("★");
        }
        document.write("<br/>");
    }
    
    //9*9乘法表
    for (var i = 1; i <= 9; i++) {//控制的行数
        document.write("<tr>");
        for (var j = 1; j <= i; j++) {
            document.write("<td>");
            document.write(i + "*" + j + "=" + i * j);
            document.write("</td>");
        }
        document.write("</tr>");
    }
    document.write("</table>");
    
    
  • 三元运算
    var a = 1;
    var b = 2;
    var c = a > b ? a : b //如果a>b这个条件成立,就把冒号前面的值给c,否则把冒号后面的值给c   //python中的:a = x if x>y else y
    
    

函数部分

  • 函数的定义:JavaScript中的函数和Python中的非常类似,只是定义方式有点区别。
    //1 普通函数定义
    function f1() {
      console.log("Hello world!");
    }
    
    //2 带参数的函数
    function f2(a, b) {
      console.log(arguments);  //内置的arguments对象;打印结果:Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
      console.log(arguments.length);  //2;参数长度
      console.log(a, b);  //1,2
    }
    f2(1,2)  //调用函数
    
    //3 带返回值的函数
    function sum(a, b){
      return a + b;  //在js中,如果你想返回多个值是不行的,比如return a ,b;只能给你返回最后一个值,如果就想返回多个值,你可以用数组包裹起来 return [a,b];
    }
    ret=sum(1, 2);  // 调用函数 sum(1,2,3,4,5)参数给多了,也不会报错,还是执行前两个参数的和,sum(1),少参数或者没参数也不报错,不过返回值就会是NAN,ret接收返回值3
    
    //4 匿名函数,多和其他函数配合使用,后面我们会用到
    var sum = function (a,b){return a+b;} //在es6中,使用var,可能会飘黄,是因为在es6中,建议你使用let来定义变量,不过不影响你使用
    ret=sum(1,3)
    
    (function(a,b) {return a+b})(1,4) //严格来说这才是匿名函数
    
    //5 (自执行函数)立即执行函数,页面加载到这里,这个函数就直接执行了,不需要被调用执行
    (function(a, b){
        this //指向window
       return a + b;
    })(1, 2);     //python中写可以这么写:ret=(lambda x,y:x+y)(10,20) 然后print(ret)
    
    //6 ES6中允许使用“箭头”(=>)定义函数,可以理解为匿名函数,用的不多。
    var f = v => v;
    f(5)      //5  调用
    // 等同于
    var f = function(v){
      return v;
    }
    
    var sum = (num1, num2) => num1 + num2;
    // 等同于
    var sum = function(num1, num2){
      return num1 + num2;
    }
    
    //全局作用域下,函数作用域,资质行函数都执行window,函数作用域中的this指向可以发生改变,可以使用call()或则apply()
    var obj ={name:'mjj'}
    function fn(){
        console.log(this.name);
    }
    fn(); //是空值,因为函数内部this指向window
    fn.call(obj) //此时函数内部的this指向obj
    
    
  • 函数中的arguments参数
    function add(a,b){
      console.log(a+b);  //3
      console.log(arguments.length) //2 获取传入的参数的个数,arguments就是指的你传入的所有的实参,放在一个数组里面,这个arguments.length是统计这个数组的元素的个数。
    }
    
    add(1,2)
    #注意:函数只能返回一个值,如果要返回多个值,只能将其放在数组或对象中返回。
    
    
  • 函数的全局变量和局部变量
    • 局部变量:

      在JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它(该变量的作用域是函数内部)。只要函数运行完毕,本地变量就会被删除。
      
      
    • 全局变量:

       在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它。
       可以不使用var定义变量,但这样定义的变量是全局变量。
       
       function a() {
           var n1=1; 
           n2=2;  // 未使用var,表示n2是全局变量
           console.log(n1+','+n2);
       }
      a();
      console.log(n2);
      console.log(window.n2); 
      console.log(window.n1);  //全局调不到n1
      console.log(n1); //报错
      
      #结果
      1,2
      2
      2
      undefined
      报错,n1为定义
      
      
    • 变量生存周期:

      JavaScript变量的生命期从它们被声明的时间开始。
      局部变量会在函数运行以后被删除。
      全局变量会在页面关闭后被删除。
      
      
    • 作用域:

      首先在函数内部查找变量,找不到则到外层函数查找,逐步找到最外层
      #示例一
      var city = "BeiJing";
      function f() {
        var city = "ShangHai";
        function inner(){
          var city = "ShenZhen";
          console.log(city);
        }
        inner();
      }
      
      f();  //输出结果是? ---> ShenZhen
      
      #示例二
      var city = "BeiJing";
      function Bar() {
        console.log(city);
      }
      function f() {
        var city = "ShangHai";
        return Bar;
      }
      var ret = f();
      ret();  // 打印结果是?---> BeiJing
      
      #示例三:闭包
      var city = "BeiJing";
      function f(){
          var city = "ShangHai";
          function inner(){
              console.log(city);
          }
          return inner;
      }
      var ret = f();
      ret();   //---> ShangHai
      
      

词法分析

  • JavaScript中在调用函数的那一瞬间,会先进行词法分析。

  • 词法分析的过程:
    当函数调用的前一瞬间,会先形成一个激活对象:Avtive Object(AO),并会分析以下3个方面:
    
          1:函数参数,如果有,则将此参数赋值给AO,且值为undefined。如果没有,则不做任何操作,但是一般有参数的时候,我们在执行函数的时				候就把参数赋值给了这个参数,所以不会打印出undefined的效果。(如果有参数,将参数赋值未undefined占位,因为现在还没调用		          即不知道参数,所以需要undefined占位,也就是我们有时会看见为什么老是出现undefined的原因
          2:函数局部变量,如果AO上有同名的值,则不做任何操作。如果没有,则将此变量赋值给AO,并且值为undefined。
          3:函数声明,如果AO上有,则会将AO上的对象覆盖。如果没有,则不做任何操作。
        			函数内部无论是使用参数还是使用局部变量都到AO上找。
        			
    #例1
    var age = 18;
    function foo(){
      console.log(age);  //分析到这一步的时候,发现你下面有age变量声明,那么age变量就在AO对象上树上了,并且值为undefined,所以函数在执行的时候,还没有到age=22这步的时候,age=undefined,此时只知道要用age,所以先undefined占位
      var age = 22;      //如果没有这个变量声明,那么打印的结果应该是18
      console.log(age);
    }
    foo();  // 问:执行foo()之后的结果是?
    
    #结果
    //undefined
    //22
    
    #例2
    var age = 18;
    function foo(){
      console.log(age);
      var age = 22;
      console.log(age);
      function age(){   //发现age这个函数名也是变量,将OA上的变量给替换了,那么函数在执行的时候,去OA上找,发现OA是个函数,然后执行到age=22的时候,age才被重新赋值
        console.log("呵呵");
      }
      console.log(age);
    }
    foo();  // 执行后的结果是?
    
    #结果:
      function age(){
        console.log("呵呵");
      }
      22
      22
    
    

面向对象

  • 之前我们创建对象

    var person=new Object();  // 创建一个person对象
    person.name="Alex";  // person对象的name属性
    person.age=18;  // person对象的age属性
    
    
  • 面向对象,在ES5中没有类的概念,只有个构造函数,命名的首字母要大写,实例化的时候使用new关键字进行实例化
    function Person(name){
        this.name=name
    }
    
    console.log(p1.name)  
    Person.prototype.func1 = function(){  //添加一些方法,使用prototype,叫做原型链方法
        console.log(this.name,'爱编程!')   //this相当于self
    }
    var p1 = new Person('chao');
    p1.func1() //方法和属性只能通过对象来调用,不能使用类名来调用
    
    #结果
    //chao
    //chao 爱编程!
    
    
  • 注意:

    ES6中提供了Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。也就是说,Object结构提供了“字符串--值”的对应,Map结构提供了“值--值”的对应,是一种更完善的Hash结构实现。

  • map的使用
    var m = new Map();
    var o = {p: "Hello World"}
    
    m.set(o, "content")  //这里相当于创建了一个键值对,这里的键可以是很多东西
    m.get(o)  // 用键取值"content"
    
    m.has(o)  // true
    m.delete(o)  // true
    m.has(o) // false
    
    
  • JavaScript面向对象之继承
    // 父类构造函数
    var Car = function (loc) {
      this.loc = loc;
    };
    
    // 父类方法
    Car.prototype.move = function () {
      this.loc ++;
    };
    
    // 子类构造函数
    var Van = function (loc) {
      Car.call(this, loc);
    };
    
    // 继承父类的方法
    Van.prototype = Object.create(Car.prototype);
    // 修复 constructor
    Van.prototype.constructor = Van;
    // 扩展方法
    Van.prototype.grab = function () {
      /* ... */
    };
    
    

Date对象

  • Date对象属性

  • 创建Date对象

    //方法1:不指定参数
    var d1 = new Date(); //获取当前时间
    console.log(d1.toLocaleString());  //当前时间日期的字符串表示 2019/5/6 下午8:06:27
    //方法2:参数为日期字符串
    var d2 = new Date("2004/3/20 11:12");
    console.log(d2.toLocaleString());     //2004/3/20 上午11:12:00
    var d3 = new Date("04/03/20 11:12");  //月/日/年(可以写成04/03/2020)
    console.log(d3.toLocaleString());   //2020/4/3 上午11:12:00
    //方法3:参数为毫秒数,了解一下就行
    var d3 = new Date(5000);  
    console.log(d3.toLocaleString()); //1970/1/1 上午8:00:05
    console.log(d3.toUTCString());   //Thu, 01 Jan 1970 00:00:05 GMT
     
    //方法4:参数为年月日小时分钟秒毫秒
    var d4 = new Date(2004,2,20,11,12,0,300);
    console.log(d4.toLocaleString());  //2004/3/20 上午11:12:00 毫秒并不直接显示
    
    
  • Date对象的方法

    var d = new Date(); 
    d.getDate()                 获取日
    //getDay ()                 获取星期 ,数字表示(0-6),周日数字是0
    //getMonth ()               获取月(0-11,0表示1月,依次类推)
    //getFullYear ()            获取完整年份
    //getHours ()               获取小时
    //getMinutes ()             获取分钟
    //getSeconds ()             获取秒
    //getMilliseconds ()        获取毫秒
    d.getTime ()                返回累计毫秒数(从1970/1/1午夜),时间戳
    
    //格式化
    d.toLocalString()   // 2018/08/21 下午21:20:23
    d.toLocalDateString()
    
    

Json对象

  • var str1 = '{"name": "chao", "age": 18}';
    var obj1 = {"name": "chao", "age": 18};
    // JSON字符串转换成对象
    var obj = JSON.parse(str1); 
    // 对象转换成JSON字符串
    var str = JSON.stringify(obj1);
    
    

Math对象

  • Math:不需要new来创建对象,直接使用Math.下面的方法

    Math.abs(x)      返回数的绝对值。
    exp(x)      返回 e 的指数。
    floor(x)    小数部分进行直接舍去。
    log(x)      返回数的自然对数(底为e)。
    max(x,y)    返回 x 和 y 中的最高值。
    min(x,y)    返回 x 和 y 中的最低值。
    pow(x,y)    返回 x 的 y 次幂。
    random()    返回 0 ~ 1 之间的随机数。(鼓头不顾尾)
    round(x)    把数四舍五入为最接近的整数。(在同为.5时,会选择偶数)
    sin(x)      返回数的正弦。
    sqrt(x)     返回数的平方根。
    tan(x)      返回角的正切。
    Math.ceil()  向上取整,天花板函数
    Math.floor() 向下取整,地板函数
    
    function random (min,max){
      return Math.floor(Math.random()*(max-min)) + min;
    }
    
    
  • RegExp对象

    RegExp相关:用的比较多 
    //RegExp对象
    
    //创建正则对象方式1
    // 参数1 正则表达式(不能有空格)
    // 参数2 匹配模式:常用g(全局匹配;找到所有匹配,而不是在第一个匹配后停止)和i(忽略大小写)
    
    // 用户名只能是英文字母、数字和_,并且首字母必须是英文字母。长度最短不能少于6位 最长不能超过12位。
    
    // 创建RegExp对象方式(逗号后面不要加空格),假如匹配用户名是只能字母开头后面是字母加数字加下划线的5到11位的
    var reg1 = new RegExp("^[a-zA-Z][a-zA-Z0-9_]{5,11}$"); //注意,写规则的时候,里面千万不能有空格,不然匹配不出来你想要的内容,除非你想要的内容本身就想要空格,比如最后这个{5,11},里面不能有空格
    
    // 匹配响应的字符串
    var s1 = "bc123";
    
    //RegExp对象的test方法,测试一个字符串是否符合对应的正则规则,返回值是true或false。
    reg1.test(s1);  // true
    
    // 创建方式2,简写的方式
    // /填写正则表达式/匹配模式(逗号后面不要加空格)
    var reg2 = /^[a-zA-Z][a-zA-Z0-9_]{5,11}$/; 
    
    reg2.test(s1);  // true
    
    注意,此处有坑:如果你直接写一个reg2.test(),test里面啥也不传,直接执行,会返回一个true,用其他的正则规则,可能会返回false,是因为,test里面什么也不传,默认传的是一个undefined,并且给你变成字符串undefined,所以能够匹配undefined的规则,就能返回true,不然返回false
    
    
    // String对象与正则结合的4个方法
    var s2 = "hello world";
    
    s2.match(/o/g);         // ["o", "o"]             查找字符串中 符合正则 的内容 ,/o/g后面这个g的意思是匹配所有的o,
    s2.search(/h/g);        // 0                      查找字符串中符合正则表达式的内容位置,返回第一个配到的元素的索引位置,加不加g效果相同
    s2.split(/o/g);         // ["hell", " w", "rld"]  按照正则表达式对字符串进行切割,得到一个新值,原数据不变
    s2.replace(/o/g, "s");  // "hells wsrld"          对字符串按照正则进行替换
    
    // 关于匹配模式:g和i的简单示例
    var s1 = "name:Alex age:18";
    
    s1.replace(/a/, "哈哈哈");      // "n哈哈哈me:Alex age:18"
    s1.replace(/a/g, "哈哈哈");     // "n哈哈哈me:Alex 哈哈哈ge:18"      全局匹配
    s1.replace(/a/gi, "哈哈哈");    // "n哈哈哈me:哈哈哈lex 哈哈哈ge:18"  不区分大小写
    
    
    // 注意事项1:
    // 如果regExpObject带有全局标志g,test()函数不是从字符串的开头开始查找,而是从属性regExpObject.lastIndex所指定的索引处开始查找。
    // 该属性值默认为0,所以第一次仍然是从字符串的开头查找。
    // 当找到一个匹配时,test()函数会将regExpObject.lastIndex的值改为字符串中本次匹配内容的最后一个字符的下一个索引位置。
    // 当再次执行test()函数时,将会从该索引位置处开始查找,从而找到下一个匹配。
    // 因此,当我们使用test()函数执行了一次匹配之后,如果想要重新使用test()函数从头开始查找,则需要手动将regExpObject.lastIndex的值重置为 0。
    // 如果test()函数再也找不到可以匹配的文本时,该函数会自动把regExpObject.lastIndex属性重置为 0。
    
    var reg3 = /foo/g;
    // 此时 regex.lastIndex=0
    reg3.test('foo'); // 返回true
    // 此时 regex.lastIndex=3
    reg3.test('xxxfoo'); // 还是返回true
    // 所以我们在使用test()方法校验一个字符串是否完全匹配时,一定要加上^和$符号,把匹配规则写的确定一些,尽量不用上面这种的写法/xxx/。
    
    // 注意事项2(说出来你可能不信系列):
    // 当我们不加参数调用RegExpObj.test()方法时, 相当于执行RegExpObj.test(undefined),然后将这个undefined又转为字符串"undefined",去进行匹配了, 并且/undefined/.test()默认返回true。
    var reg4 = /^undefined$/;
    reg4.test(); // 返回true
    reg4.test(undefined); // 返回true
    reg4.test("undefined"); // 返回true
    
    

JavaScript全局对象

  • 全局属性和函数可用于所有内建的 JavaScript 对象。类似于Python的内置函数和方法。全局对象只是一个对象,而不是类。既没有构造函数,也无法实例化一个新的全局对象。在 JavaScript 代码嵌入一个特殊环境中时,全局对象通常具有环境特定的属性。

  • 顶层函数:

  • 顶级属性:

  • 在 JavaScript 核心语言中,全局对象的预定义属性都是不可枚举的,所有可以用 for/in 循环列出所有隐式或显式声明的全局变量,如下所示:

    var variables = "";
    for (var name in this) 
    {
    	variables += name + "、";
    }
    document.write(variables);
    
    

  • JavaScript的一些注意点
    //with 本意是减少键盘输入。比如
    
    obj.a = obj.b;
    obj.c = obj.d;
    可以简写为(类似于python的上下文处理)
    with(obj) {
        a = b;
        c = d;
    }
    
    //不要使用eval,eval用来直接执行一个字符串。这条语句也是不应该使用的,因为它有性能和安全性的问题,并且使得代码更难阅读。
    eval("myValue = myObject." + myKey + ";");
    等价于
    myValue = myObject[myKey];
    
    //continue  这条命令的作用是返回到循环的头部,但是循环本来就会返回到头部。所以通过适当的构造,完全可以避免使用这条命令,使得效率得到改善。
    
    //switch 贯穿 witch结构中的case语句,默认是顺序执行,除非遇到break,return和throw。有的程序员喜欢利用这个特点,比如
    switch(n) {
        case 1:
        case 2:
            break; //因此建议避免switch贯穿,凡是有case的地方,一律加上break。
    }
    
    //单行的块结构,if、while、do和for,都是块结构语句,但是也可以接受单行命令。比如
    if (ok) t = true;
    等价于
    if (ok){
        t = true;
      }
    
    //function语句 在JavaScript中,函数有以下两种定义方式:
    function foo() { }
    var foo = function () { }
    	两种写法完全等价。但是在解析的时候,前一种写法会被解析器自动提升到代码的头部,因此违背了函数应该先定义后使用的要求,所以建议定义函数时,全部采用后一种写法。
        
    
    #new语句:Javascript是世界上第一个被大量使用的支持Lambda函数的语言,本质上属于与Lisp同类的函数式编程语言。但是当前世界,90%以上的程序员都是使用面向对象编程。为了靠近主流,Javascript做出了妥协,采纳了类的概念,允许根据类生成对象。类是这样定义的:
    var Cat = function (name) {
        this.name = name;
        this.saying = 'meow' ;
    }
    #然后生成一个对象
    var myCat = new Cat('mimi');
    这种利用函数生成类、利用new生成对象的语法,其实非常奇怪,一点都不符合直觉。而且,使用的时候,很容易忘记加上new,就会变成执行函数,然后莫名其妙多出几个全局变量。所以,建议不要这样创建对象,而采用一种变通方法。
    #Douglas Crockford给出了一个函数:
    Object.beget = function (o) {
        var F = function (o) {};
        F.prototype = o ;
        return new F;
    };
    #创建对象时就利用这个函数,对原型对象进行操作:
    var Cat = {
        name:'',
        saying:'meow'
    };
    
    var myCat = Object.beget(Cat);
    对象生成后,可以自行对相关属性进行赋值:  myCat.name = 'mimi';
    
    

数值和字符串转换

1、数值转字符串
toString()     //方式一
数字+空的字符串  //方式二

2、字符串转数值
parseInt()  //转整数
parseFloat()  //转浮点型
Number()

3、NAN  //Not a Number
isNAN  //判断是否不是数值
document.write(isNaN(123)); //false
document.write(isNaN("Hello")); //true

4、infinty  //无限大
7/0

posted @ 2019-06-04 17:41  独角兕大王  阅读(440)  评论(0)    收藏  举报