美文网首页
js学习笔记

js学习笔记

作者: crabor | 来源:发表于2018-10-18 16:50 被阅读0次

    js学习笔记

    语法

    后续补充笔记

    • join()方法

      var fruits = ["Banana", "Orange", "Apple", "Mango"];
      var energy = fruits.join(" and ");
      //Banana and Orange and Apple and Mango
      

    循环

    • for...in

      for循环的一个变体是for ... in循环,它可以把一个对象的所有属性依次循环出来:

      var o = {
        name: 'Jack',
        age: 20,
        city: 'Beijing'
        };
        for (var key in o) {
            console.log(key); // 'name', 'age', 'city'
        }
      
    • for...of

      遍历Array可以采用下标循环,遍历MapSet就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable类型,ArrayMapSet都属于iterable类型。

      具有iterable类型的集合可以通过新的for ... of循环来遍历。

      for ... of循环是ES6引入的新的语法

      'use strict';
      var a = [1, 2, 3];
      for (var x of a) {
      }
      

    你可能会有疑问,for ... of循环和for ... in循环有何区别?

    for ... in循环由于历史遗留问题,它遍历的实际上是对象的属性名称。一个Array数组实际上也是一个对象,它的每个元素的索引被视为一个属性。

    当我们手动给Array对象添加了额外的属性后,for ... in循环将带来意想不到的意外效果:

    var a = ['A', 'B', 'C'];
    a.name = 'Hello';
    for (var x in a) {
        console.log(x); // '0', '1', '2', 'name'
    }
    

    for ... in循环将把name包括在内,但Arraylength属性却不包括在内。

    for ... of循环则完全修复了这些问题,它只循环集合本身的元素:

    var a = ['A', 'B', 'C'];
    a.name = 'Hello';
    for (var x of a) {
        console.log(x); // 'A', 'B', 'C'
    }
    

    这就是为什么要引入新的for ... of循环。

    函数

    • 函数定义

      //第一种定义
      function abs(x) {
          if (x >= 0) {
              return x;
          } else {
              return -x;
          }
      }
      //第二种定义
      var abs = function (x) {
          if (x >= 0) {
              return x;
          } else {
              return -x;
          }
      };
      
    • arguments

      JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array

      function foo(x) {
          console.log('x = ' + x); // 10
          for (var i=0; i<arguments.length; i++) {
              console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
          }
      }
      foo(10, 20, 30);
      
      //x = 10
      //arg 0 = 10
      //arg 1 = 20
      //arg 2 = 30
      
    • rest参数

      由于JavaScript函数允许接收任意个参数,于是我们就不得不用arguments来获取所有参数:

      function foo(a, b, ...rest) {
          console.log('a = ' + a);
          console.log('b = ' + b);
          console.log(rest);
      }
      
      foo(1, 2, 3, 4, 5);
      // 结果:
      // a = 1
      // b = 2
      // Array [ 3, 4, 5 ]
      
      foo(1);
      // 结果:
      // a = 1
      // b = undefined
      // Array []
      
    • return语句

      //错误
      function foo() {
          return
              { name: 'foo' };
      }
      foo(); // undefined
      
      //正确
      function foo() {
          return { // 这里不会自动加分号,因为{表示语句尚未结束
              name: 'foo'
          };
      }
      
    • 变量提升

      JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:

      'use strict';
      
      function foo() {
          var x = 'Hello, ' + y;
          console.log(x);
          var y = 'Bob';
      }
      
      foo();
      

      虽然是strict模式,但语句var x = 'Hello, ' + y;并不报错,原因是变量y在稍后申明了。但是console.log显示Hello, undefined,说明变量y的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。

      对于上述foo()函数,JavaScript引擎看到的代码相当于:

      function foo() {
          var y; // 提升变量y的申明,此时y为undefined
          var x = 'Hello, ' + y;
          console.log(x);
          y = 'Bob';
      }
      

      由于JavaScript的这一怪异的“特性”,我们在函数内部定义变量时,请严格遵守“在函数内部首先申明所有变量”这一规则。最常见的做法是用一个var申明函数内部用到的所有变量:

      function foo() {
          var
              x = 1, // x初始化为1
              y = x + 1, // y初始化为2
              z, i; // z和i为undefined
          // 其他语句:
          for (i=0; i<100; i++) {
              ...
          }
      }
      
    • 全局作用域

      不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性

    • 常量

      使用关键字const

    • 解构赋值

      'use strict';
      
      // 如果浏览器支持解构赋值就不会报错:
      var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
      // x, y, z分别被赋值为数组对应元素:
      console.log('x = ' + x + ', y = ' + y + ', z = ' + z);
      
      //x = hello, y = JavaScript, z = ES6
      
      let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
      x; // 'hello'
      y; // 'JavaScript'
      z; // 'ES6'
      
      let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素
      z; // 'ES6'
      
      'use strict';
      
      var person = {
          name: '小明',
          age: 20,
          gender: 'male',
          passport: 'G-12345678',
          school: 'No.4 middle school'
      };
      var {name, age, passport} = person;
      // name, age, passport分别被赋值为对应属性:
      console.log('name = ' + name + ', age = ' + age + ', passport = ' + passport);
      
      var person = {
          name: '小明',
          age: 20,
          gender: 'male',
          passport: 'G-12345678',
          school: 'No.4 middle school',
          address: {
              city: 'Beijing',
              street: 'No.1 Road',
              zipcode: '100001'
          }
      };
      var {name, address: {city, zip}} = person;
      name; // '小明'
      city; // 'Beijing'
      zip; // undefined, 因为属性名是zipcode而不是zip
      // 注意: address不是变量,而是为了让city和zip获得嵌套的address对象的属性:
      address; // Uncaught ReferenceError: address is not defined
      

      有些时候,如果变量已经被声明了,再次赋值的时候,正确的写法也会报语法错误:

      // 声明变量:
      var x, y;
      // 解构赋值:
      {x, y} = { name: '小明', x: 100, y: 200};
      // 语法错误: Uncaught SyntaxError: Unexpected token =
      

      这是因为JavaScript引擎把{开头的语句当作了块处理,于是=不再合法。解决方法是用小括号括起来:

      ({x, y} = { name: '小明', x: 100, y: 200});
      
    • this指针

      ECMA决定,在strict模式下让函数的this指向undefined,因此,在strict模式下,你会得到一个错误:

      'use strict';
      
      var xiaoming = {
          name: '小明',
          birth: 1990,
          age: function () {
              var y = new Date().getFullYear();
              return y - this.birth;
          }
      };
      
      var fn = xiaoming.age;
      fn(); // Uncaught TypeError: Cannot read property 'birth' of undefined
      

      这个决定只是让错误及时暴露出来,并没有解决this应该指向的正确位置。

      有些时候,喜欢重构的你把方法重构了一下:

      'use strict';
      
      var xiaoming = {
          name: '小明',
          birth: 1990,
          age: function () {
              function getAgeFromBirth() {
                  var y = new Date().getFullYear();
                  return y - this.birth;
              }
              return getAgeFromBirth();
          }
      };
      
      xiaoming.age(); // Uncaught TypeError: Cannot read property 'birth' of undefined
      

      结果又报错了!原因是this指针只在age方法的函数内指向xiaoming,在函数内部定义的函数,this又指向undefined了!(在非strict模式下,它重新指向全局对象window!)

      修复的办法也不是没有,我们用一个that变量首先捕获this:

      'use strict';
      
      var xiaoming = {
          name: '小明',
          birth: 1990,
          age: function () {
              var that = this; // 在方法内部一开始就捕获this
              function getAgeFromBirth() {
                  var y = new Date().getFullYear();
                  return y - that.birth; // 用that而不是this
              }
              return getAgeFromBirth();
          }
      };
      
      xiaoming.age(); // 25
      

      var that = this;,你就可以放心地在方法内部定义其他函数,而不是把所有语句都堆到一个方法中。

    • 其他

      map()filter()sort()函数

    标准对象

    • Date

      var now = new Date();
      now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
      now.getFullYear(); // 2015, 年份
      now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
      now.getDate(); // 24, 表示24号
      now.getDay(); // 3, 表示星期三
      now.getHours(); // 19, 24小时制
      now.getMinutes(); // 49, 分钟
      now.getSeconds(); // 22, 秒
      now.getMilliseconds(); // 875, 毫秒数
      now.getTime(); // 1435146562875, 以number形式表示的时间戳
      

      如果要创建一个指定日期和时间的Date对象,可以用:

      var d = new Date(2015, 5, 19, 20, 15, 30, 123);
      d; // Fri Jun 19 2015 20:15:30 GMT+0800 (CST)
      

      注意!!!:你可能观察到了一个非常非常坑爹的地方,就是JavaScript的月份范围用整数表示是0~11,0表示一月,1表示二月……,所以要表示6月,我们传入的是5!这绝对是JavaScript的设计者当时脑抽了一下,但是现在要修复已经不可能了。

      时区

      var d = new Date(1435146562875);
      d.toLocaleString(); // '2015/6/24 下午7:49:22',本地时间(北京时区+8:00),显示的字符串与操作系统设定的格式有关
      d.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT',UTC时间,与本地时间相差8小时
      
    • JSON

      'use strict';
      
      var xiaoming = {
          name: '小明',
          age: 14,
          gender: true,
          height: 1.65,
          grade: null,
          'middle-school': '\"W3C\" Middle School',
          skills: ['JavaScript', 'Java', 'Python', 'Lisp']
      };
      
      //{"name":"小明","age":14,"gender":true,"height":1.65,"grade":null,"middle-school":"\"W3C\" Middle School","skills":["JavaScript","Java","Python","Lisp"]}
      

    面向对象编程

    • 原型

      'use strict';
      function Student(name) {
          this.name=name;
      }
      
      Student.prototype.hello=function(){
          return 'Hello, '+this.name+'!';
      }
      //var xiaoming = new Student('小明');
      //xiaoming.hello();
      
    • class

      class Student {
          constructor(name) {
              this.name = name;
          }
      
          hello() {
              alert('Hello, ' + this.name + '!');
          }
      }
      //var xiaoming = new Student('小明');
      //xiaoming.hello();
      
    • class继承

      class PrimaryStudent extends Student {
          constructor(name, grade) {
              super(name); // 记得用super调用父类的构造方法!
              this.grade = grade;
          }
      
          myGrade() {
              alert('I am at grade ' + this.grade);
          }
      }
      

    相关文章

      网友评论

          本文标题:js学习笔记

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