廖雪峰 JavaScript 教程-notes

之前看廖雪峰的git教程觉得很好,当时就注意到有js的教程,在w3school看了觉得函数部分讲的不太好,所以来看廖雪峰的

下面笔记开始

基本语法

1. string

  1. 字符串拼接

如果有很多变量需要连接,用+号就比较麻烦。ES6新增了一种模板字符串,表示方法和上面的多行字符串一样,但是它会自动替换字符串中的变量:

var name = '小明';
var age = 20;
alert(`你好, ${name}, 你今年${age}岁了!`);
  1. 字符串是不可变的,当然同样的方法,array里的元素是可以被改变的
var s = 'Test';
s[0] = 'X';
alert(s); // s仍然为'Test'
  1. string的几个常用方法
var s = 'Hello';
s.toUpperCase(); // 返回'HELLO'
s.toLowerCase();//返回‘hello’
s.indexOf('ll');//返回2;如果返回-1说明没有匹配字符串
s.substring(0,3)//返回[0,3)字符串,区间左闭右开;如果只有一个参数,返回从该参数到最后的substring

2. array

  1. 如果通过索引赋值时,索引超过了范围,不会报错!
var arr = [1, 2, 3];arr[5] = 'x';arr; // arr变为[1, 2, 3, undefined, undefined, 'x']
  1. 也有indexOf();的方法,也是如果找不到对应元素就返回-1,其他情况返回对应索引
  2. slice() similar as string.substring()
arr.slice(0, 3); // 从索引0开始,到索引3结束,但不包括索引3
arr.slice(3); // 从索引3开始到结束: ['D', 'E', 'F', 'G']
arr.slice();//整个原arr,但是原arr的复制品,用===判定是否相同会返回false
  1. arr.push()------arr.pop(),尾部追加和推出最后一个元素
    arr.unshift()------arr.shift(),头部添加和删除第一个元素
  2. 排序,反转
arr.sort();
arr.reverse();
  1. splice:从指定的索引开始删除若干元素,然后再从该位置添加若干元素
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 从索引2开始删除3个元素,然后再添加两个元素:
arr.splice(2, 3, 'Google', 'Facebook'); 
// 只删除,不添加:
arr.splice(2, 2); 
// 只添加,不删除:
arr.splice(2, 0, 'Google', 'Facebook'); 
  1. concat,把作为参数的数组拼接在原数组后面
arr.concat([1, 2, 3])

请注意,concat()方法并没有修改当前Array,而是返回了一个新的Array。
实际上,concat()方法可以接收任意个元素和Array,并且自动把Array拆开,然后全部添加到新的Array里:

var arr = ['A', 'B', 'C'];
arr.concat(1, 2, [3, 4]); // ['A', 'B', 'C', 1, 2, 3, 4]
  1. join 用指定符号连接数组中元素
var arr = ['A', 'B', 'C', 1, 2, 3];
arr.join('-'); // 'A-B-C-1-2-3'

3. object

  1. 可以用.propName或["propName"]这两种方式引用obj的prop
  2. 删除属性:delete xiaoming.school;
    删除一个不存在的school属性也不会报错
  3. 用in判断obj有没有某属性(包括自己的也包括继承来的):'name' in xiaoming;
    用hasOwnProperty判断是不是自身的(不包括继承来的):xiaoming.hasOwnProperty('name');

4. if

跟其他语言一样的特性,注意逻辑清楚才能写对代码

5. loop

  1. for循环的3个条件都是可以省略的for( ; ; ){...},如果没有退出循环的判断条件,就必须使用break语句退出循环,否则就是死循环
  2. for in 可以把obj的所以prop列举出来
var o = { name: 'Jack', age: 20, city: 'Beijing'};
for (var key in o) {
       alert(key); // 'name', 'age', 'city'
}

array也是obj,所以arr也可以用

var a = ['A', 'B', 'C'];
for (var i in a) { 
      alert(i); // '0', '1', '2'注意这里是string不是num
       alert(a[i]); // 'A', 'B', 'C'
}
  1. while 和do while,都完全可以用for取代,尤其do while用的更少

6. Map,Set

  1. JavaScript的默认对象表示方式{}可以视为其他语言中的Map或Dictionary的数据结构,即一组键值对。要求key必须为string,但ES6规范引入了新的数据类型Map,支持其他类型的key,比如数字
  2. map常用操作:(多次对一个key放入value,后面的值会把前面的值冲掉)
var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
  1. set很像java中set,类似数组但不存储重复值
    方法也类似,比如:
s.add();
s.delete();
  1. iterable类型可以用for of 来遍历
    Map Set Array都属于iterable类型,
var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { 
      // 遍历Array
       alert(x);
}
for (var x of s) { 
      // 遍历Set
       alert(x);
}
for (var x of m) { 
      // 遍历Map 
      alert(x[0] + '=' + x[1]);
}
  1. iterable内置的forEach方法
var a = ['A', 'B', 'C'];
a.forEach(function (element, index, array) { 
      // element: 指向当前元素的值 // index: 指向当前索引 // array: 指向Array对象本身
      alert(element);
});
//set没有索引,所以第二个参数是sameElement
var s = new Set(['A', 'B', 'C']);
s.forEach(function (element, sameElement, set) { 
      alert(element);
});
//map:k-v
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
m.forEach(function (value, key, map) { 
      alert(value);
});
//如果对其中一些参数没有兴趣,可以直接省略不写

函数 function

  1. arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array。
    argument可以获得传入的所有参数,即使函数不定义任何参数
    argument常用语判断传入参数的个数例子

    廖雪峰 JavaScript 教程-notes_第1张图片
    argument功能介绍

    廖雪峰 JavaScript 教程-notes_第2张图片
    argument常用方法

  2. rest 获取剩余的参数,有点像go里的可变参数,rest只能写在最后,如果正常参数都没传够,rest是一个空数组,而不是undefined

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 ]
廖雪峰 JavaScript 教程-notes_第3张图片
原站例子
  1. return 如果要返回一堆记得加大括号,直接return 换行 returnContent,returnContent这句将执行不到(因为return后会自动加;程序就返回了)
  2. 变量作用域:
    a...函数内的作用域是函数内,所以不同函数可以有同名变量;
    b...js引擎会自动提升所有变量的声明但不提升赋值;
    c...变量从内向外查找,内部会屏蔽外部重名变量
    d...JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性,有个好的方法就是把自己所有变量和函数都绑定到一个全局变量中
// 唯一的全局变量
MYAPP:var MYAPP = {};
// 其他变量:
MYAPP.name = 'myapp';
MYAPP.version = 1.0;
// 其他函数:
MYAPP.foo = function () { 
return 'foo';
};

e...let在for循环中可以替代var,声明一个块级作用域的变量for (let i=0; i<100; i++) {...}
f...常量 const,默认不能被更改的,如果又重新赋值想修改,不会报错,但修改不会生效

  1. 在一个对象中绑定函数,称为这个对象的方法,通过object.method()的形式调用(确保this指向正确)
  2. 有个this指向的坑,可能是你以为指向了obj,然而指向了全局window,需要var that=this;例子;或者用apply,例子还在左边的链接里,用途是会把想指向的obj打包成array当做参数传入,call也有类似的作用,把参数按顺序传入
    Math.max.apply(null, [3, 5, 4]); // 5 Math.max.call(null, 3, 5, 4); // 5
  3. 装饰器,利用apply,动态改变函数行为。例子是想统计调用了多少次某方法,链接上面
  4. higher-order function 一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。跟go里也有地方很像,比如filepath.Walk(root,walkfunc)这样老根其他语言比较好像不太好。。憋学我
  5. 讲map的时候的一个例子,看起来好不习惯,就是把原arr中都map(同过一个映射关系映射成别的样子)成string(我也不知道该怎么说了
function pow(x) { return x * x;}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(pow); 
// [1, 4, 9, 16, 25, 36, 49, 64, 81]
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(String); // ['1', '2', '3', '4', '5', '6', '7', '8', '9']

如果不给pow传参数,说明pow是某obj的方法,比如arr.map所以直接用obj调用了,可能是这样吧.或者理解成map前面那货是后面这个函数的参数,看怎么理解记住的快了。
map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把Array的所有数字转为字符串。

  1. reduce,根据例子加之前对mapreduce的印象大概就是把同类,或者子问题,先解决,从而帮助解决其他同类或者父问题
    [x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
    应用,比如求和:
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) { return x + y;}); // 25
  1. filter,把array的某些元素过滤掉返回剩下元素,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。例子
  2. sort 大小写敏感,所有元素转string后排序,会直接修改array
  3. 闭包(多年后我终于又回来看了闭包
function count() { 
      var arr = [];
      for (var i=1; i<=3; i++) { 
            arr.push(function () {
                   return i * i; 
            }); 
      } 
return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // 16
f2(); // 16
f3(); // 16

这段代码是个典型的闭包例子,function () {return i * i; }这个funtion引用了函数外的变量i,
最后的输出结果都为16,可以看出,在执行f1,f2,f3时,i=4, 为什么不是想我们想的那样输出 1, 4, 9

  1. 先看results这里,results=count(); count方法调用了,也就是说results现在是count()函数的返回值,即:results=arr;
  2. 那arr里存的是什么,arr[0],arr[1],arr[3]里现在存的都是function () {return i * i; },这个function通过push方法存入数组;
  3. var f1 = results[0]其实就是arr[0]赋值给了f1,也就是说f1现在是这个函数function () {return i * i; }
  4. f1();即执行该函数。 但我们刚刚说过count()已经执行完了,所以这时候i=4,是i进不去for循环的值,所以f1();执行结果=16,剩下两个同理。

我们并没有得到想要的答案,下面看解决方案

arr.push((function (n) { 
      return function () { 
            return n * n; 
      } 
})(i));

我们通过n来保留当时的i值,
当我们执行count()的时候,向arr中push的元素变为

(function (n) { 
      return function () { 
            return n * n; 
      } 
})(i)

这个东西,函数后面跟有小括号即执行函数,小括号中i即function需要接收的参数n,所以我们push到数组里的三个元素其实是这个东西的执行结果(上面这个函数的返回值):function () {return 1 * 1; }function () {return 2* 2; }function () {return 3 * 3; }
问题解决。
剩下两个闭包例子不看了吧,随缘吧,用一用应该就会了


函数还剩下两个部分,箭头函数和generator, 都是ES6新增内容,先跳过了,先看下对象和DOM操作方面的

Object

  1. typeOf看类型
typeof 123; // 'number'
typeof NaN; // 'number'
typeof 'str'; // 'string'
typeof true; // 'boolean'
typeof undefined; // 'undefined'
typeof Math.abs; // 'function'
typeof null; // 'object'
typeof []; // 'object'
typeof {}; // 'object'

你可能感兴趣的:(廖雪峰 JavaScript 教程-notes)