javascript学习笔记(廖雪峰javascript教程)

“==/===”

  • 第一种是==比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;
  • 第二种是===比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。
  • 由于JavaScript这个设计缺陷,不要使用==比较,始终坚持使用===比较。

strict模式/变量

  • JavaScript在设计之初,为了方便初学者学习,并不强制要求用var申明变量。这个设计错误带来了严重的后果:如果一个变量没有通过var申明就被使用,那么该变量就自动被申明为全局变量:

数组Array

  • JavaScript的Array可以包含任意数据类型,并通过索引来访问每个元素。
  • 请注意,直接给Array的length赋一个新的值会导致Array大小的变化:
  • 大多数其他编程语言不允许直接改变数组的大小,越界访问索引会报错。然而,JavaScript的Array却不会有任何错误。在编写代码时,不建议直接修改Array的大小,访问索引时要确保索引不会越界。

判断对象属性

  • 如果我们要检测对象是否拥有某一属性,可以用in操作符
  • 如果in判断一个属性存在,这个属性也可能是继承得到的,要判断一个属性是否是对象自身拥有的,而不是继承得到的,可以用hasOwnProperty()方法

for in/of循环

  • for循环的一个变体是for … in循环,它可以把一个对象的所有属性依次循环出来,要过滤掉对象继承的属性,用hasOwnProperty()来实现。
  • 由于Array也是对象,而它的每个元素的索引被视为对象的属性,因此,for … in循环可以直接循环出Array的索引:(注意是索引)
    var a = ['A', 'B', 'C'];
    for (var i in a) {
        alert(i); // '0', '1', '2'
        alert(a[i]); // 'A', 'B', 'C'
    }
请注意,for ... in对Array的循环得到的是String而不是Number。
  • for … in循环由于历史遗留问题,它遍历的实际上是对象的属性名称。一个Array数组实际上也是一个对象,它的每个元素的索引被视为一个属性。当我们手动给Array对象添加了额外的属性后,for … in循环将带来意想不到的意外效果:
    var a = ['A', 'B', 'C'];
    a.name = 'Hello';
    for (var x in a) {
        alert(x); // '0', '1', '2', 'name'
    }
  • for … of循环则完全修复了这些问题,它只循环集合本身的元素:
  • 然而,更好的方式是直接使用iterable内置的forEach方法,它接收一个函数,每次迭代就自动回调该函数。

javascript中的Map/Set

Map和Set是ES6标准新增的数据类型,请根据浏览器的支持情况决定是否要使用。

Interable循环

  • 遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。
  • Array、Map和Set都属于iterable类型。
  • 具有iterable类型的集合可以通过新的for … of循环来遍历。

函数

  • 由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数,多余的会被直接忽略。
  • 传入的参数比定义的少也没有问题,相当于传递了参数undefined,计算结果为NaN,为了避免此种情况,可以在函数内部进行判断,使用typeof进行类型判断。
  • JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array。
  • 还有一个关键词rest用来获取多余的参数。

变量作用域

  • 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量,不同函数内部的同名变量互相独立,互不影响。
  • 变量提升,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部,但不会提升变量的赋值。即可以使用它,但又不能引用它的值,挺坑的。
  • 函数里面的for循环等语句块中定义的变量的作用域会扩展到函数内部。
    'use strict';

    function foo() {
        for (var i=0; i<100; i++) {
            //
        }
        i += 100; // 仍然可以引用变量i
    }
    //为了解决块级作用域,可以使用let替代var来申    明一个块级作用域的变量。
  • 使用const来定义常量,const和let都具有块级作用域。

方法

  • this表示调用方法的对象,如果直接写方法,则this相当于window,所以为了保证this指向正确,必须用obj.xxx()的形式调用!
  • 在方法内部又定义了一个方法,则this又失效了,此时可以使用一个that变量捕获this,然后就可以在内部的方法中继续使用that变量了。
  • 可以使用apply来调用方法,传入对象和参数。
  • 还可以使用call,区别是apply把参数打包成Array再传入,而call把参数按顺序传入。
  • 对普通函数调用,我们通常把this绑定成null。
  • 用新函数封装旧函数,类似于代理模式,非常棒。
    var count = 0;
    var oldParseInt = parseInt; // 保存原函数

    window.parseInt = function () {
        count += 1;
        return oldParseInt.apply(null, arguments); // 调用原函数
    };

    // 测试:
    parseInt('10');
    parseInt('20');
    parseInt('30');
    count; // 3

高阶函数

  • 函数的参数能够接收别的函数
  • Array的map()方法:传入一个函数,然后把数组元素依次传递给该函数,然后再返回一个数组。
  • Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
  • Array的sort()方法也是一个高阶函数,可以直接传入一个函数。
  • Array的reduce()把一个函数作用在这个Array的[x1, x2, x3…]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:

    [x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

你可能感兴趣的:(javascript)