廖雪峰的javascript教程笔记

2016-11-23  本文已影响0人  Zac_Evelynn

入门

数据类型和变量

数据类型

Number

String

模板字符串
var name = "lxf";
var age = 26;
var msg = '您好,$(name),您今年$(age)岁。';
操作字符串

Boolean

逻辑运算符

比较运算符

null

undefined

Array

push和pop
unshift和shift
sort
reverse
var arr = [1,2,3];
arr.reverse();
arr;  // [3,2,1]
splice
var arr = [1,2,3];
arr.splice(1,2,'a','b','c');  // [2,3]
arr; // [1,'a','b','c']
concat
var arr = [1,2,3];
var newArr = arr.concat([9,8,7]);
newArr;  // [1,2,3,9,8,7]
arr;  // [1,2,3]
var arr = [1,2,3];
var newArr = arr.concat('a','b',[9,8,7]);
newArr;  // [1,2,3,'a','b',9,8,7]
arr;  // [1,2,3]
join
var arr = [1,2,3];
arr.join('+');  // '1+2+3'

Object

变量

strict模式

条件判断

循环

for循环

for...in

var obj = {
    name: 'lxf',
    age: 26
};
for(var prop in obj){
    if(obj.hasOwnProperty(prop)){  // 过滤掉继承的属性
        console.log(prop);
    }
}
var arr = ['a','b','c'];
for(var item in arr){
    alert(item);  // "0,1,2"
    alert(arr[item]);  // 'a','b','c'
}

while循环

do...while

Map和Set

Map

var m = new Map();
m.set("name","lxf");  // 添加键值对
m.has("name");  // 是否含有name属性
m.get("name");  // 返回值lxf
m.delete("name");  // 删除name
m.get('name');  // 不存在的返回undefined

Set

iterable

for...of

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]);
}

forEach()

var arr = [1,2,3];
arr.forEach(function(element, index, array){
    // element:当前元素的值
    // index:当前元素的索引值
    // array:数组本身
    alert(element);
});

var s = new Set(['1','a','c']);
s.forEach(function(element, sameElement, set){
    // element, sameElement:当前元素本身
    // set:该set
    alert(element);
})

var m = new Map([[1,11],['asd',222],[3,'zxc']]);
m.forEach(function(value, key, map){
    // value:当前属性的值
    // key:当前属性
    // map:map本身
    alert(key + '=' + value);
})

函数

// 定义函数
function asd(){...}
var asd = function(){};

function abs(x){
    if(indexOf(x) !== 'number'){  // 如果参数不是数字,抛出异常 
        throw 'Not a number!';
    }
    if(x >= 0){
        return x;
    }else{  // 如果是负数,返回正数
        return -x;
    }
}
abs(-9);  // 9

arguments

function foo(){
    if(arguments.length === 0){
        return 0;
    }
    var arg = arguments[0];
    return arg >= 0 ? arg : -arg;
}
foo(-10);  // 10

rest参数

function abc(a, b, c, ...rest){
    alert('a='+a);  // 1
    alert('b='+b);  // 2
    alert('c='+c);  // 3
    alert('rest='+rest);  // 4,5
}
abc(1,2,3,4,5);

关于return

return {  // return的换行书写方式 
    ...
}

变量作用域

嵌套的函数出现变量重名时

function a(){
    var x = 1;
    function b(){
        var x = 'a';
        alert("b()的x=" + x);
    }
    alert("a()的x=" + x);
    b();
}

变量提升

function a(){
    var x = 1;
    alert(x+y);
    var y = 2;

    // 变量提升后的排列:
    // var y;  变量提升
    // var x = 1;
    // alert(x+y);
    // y = 2;  不会提升变量的赋值
}

全局作用域

var name = 'lxf';
alert(name);  // 'lxf'
alert(window.name);  // 'lxf'

名字空间

var myGlobal = {};
myGlobal.name = 'lxf';
myGlobal.age = 26;
myGlobal.a = function(){
    alert('您好,' + myGlobal.name + ',您今年' + myGlobal.age + '岁');
}

局部作用域

function a(){
    for(var i=0;i<10;i++){
        ...
    }
    i += 10;  // var声明的变量的作用域仍是函数体
}

function b(){
    for(let i=0;i<10;i++){
        alert(i);
    }
    alert(i);  // let声明了一个块级作用域,所以for语句外无法访问,报错Uncaught ReferenceError: i is not defined
}

常量

const a = 1;
a;  // 1
a = 2;  // Uncaught TypeError: Assignment to constant variable

方法

var menu = {
    name: '鱼香肉丝',
    price: 15,
    order: function(num){
        var msg = '您购买了' + num + '份,总价为:' + (num * this.price) + '元。';
        return msg;
    }
}

this

function orderMsg(num){
        var msg = '您购买了' + num + '份,总价为:' + (num * this.price) + '元。';
        return msg;
    }
var menu = {
    name: '鱼香肉丝',
    price: 15,
    order: orderMsg
}
menu.order(2);  //"您购买了2份,总价为:30元。"
orderMsg(2);  // NaN,直接调用函数,this指向的是window

apply和call

function getAge() { 
    var y = new Date().getFullYear();
    return y - this.birth;
}
var xiaoming = { 
    name: '小明', 
    birth: 1990, 
    age: getAge
};
xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空

Math.max.apply(null, [2,3,4]);  // 参数打包成数组传入;this绑定为null
Math.max.call(null, 2,3,4);  // 按顺序传入参数;this绑定为null

装饰器

var count = 0;
var oldAlert = window.alert;
window.alert = function(){
    count += 1;
    return oldAlert.apply(null, arguments);
};
alert(1);
alert(2);
count;  // 2

高阶函数

function toNum(a){
    var num = Number(a);
    return num;
}
function a(x,y,z){
    return z(x) + z(y);
}
a('1', '2', toNum);  // 3

map/reduce

// map()
function pow(x){
    return x * x;
}
var arr = [1,2,3,4,5];
arr.map(pow);  // [1,4,9,16,25]
// reduce()
function plus(arr){
    var val = arr.reduce(function(x,y){
        return x + y;
    });
    return val;
}
var arr = [1,2,3,5,9];
plus(arr);  // 20

练习

var arr = ['BoB', 'PaWN','ann','LEE'];
function change(arr){
    var newName = arr.map(function(name){
        var lower = name.toLowerCase();
        var upper = name[0].toUpperCase();
        return upper + lower.substring(1);
    });
    return newName;
}
change(arr);

filter

var arr = [1,2,3,4,5];
var newArr = arr.filter(function(item){
    return item % 2 === 0;
});
newArr;  // [2,4]

排序sort()

// 字符串按字母顺序排列
var arr = ['yes','app', 'ball'];
arr.sort(function(x,y){
    var first = x.toLowerCase();  // 先统一参数的大小写
    var last = y.toLowerCase();
    if(first < last){
        return -1;
    } else if(first == last){
        return 0;
    } else if(first > base){
        return 1;
    }
});  // ['app', 'ball', 'yes']

闭包

function lazy_sum(arr){
    var sum = function(){  // sum可以引用lazy_sum的参数和变量 
        return arr.reduce(function(x,y){
            return x + y;
        })
    }
    return sum;  // 返回sum函数,每次调用都会返回一个新的函数
}

// 调用
var f = lazy_sum([1,2,3,4,5]);
f();  // 15

// 一定要引用循环变量时:
function count(){
    var arr = [];
    for(var i=1;i<=3;i++){
        arr.push((function(n){
            return function(){
                return n * n;
            }
        })(i));
    }
    return arr;
}

var result = count();
var f1 = result[0];  
f1();  // 1

// 计数器
function counter(num){
    var x = num || 0;
    return {
        inc: function(){
            x += 1;
            return x;
        }
    }
}
var create = counter();
create.inc();  // 1
var create2 = counter(20);
create2.inc();  // 21

// 求根:
function newPow(n){
    return function (num){
        return Math.pow(num, n);  // num是数,n是次方
    }
}
var pow = newPow(2);
pow(3);  // 9

箭头函数

// 多语句:
x => { 
    if (x > 0) { 
        return x * x; 
    } else { 
        return - x * x; 
    }
}

// 多个参数:
(x,y)=> x * x + y * y;

// 无参数:
() => 1

// 可变参数:
(x,y,...rest) => {
    var i, 
    sum=x+y;
    for(I=0;i<rest.length;i++){
        sum += rest[I];
    }
    return sum;
}

// 如果要返回一个对象:
x => {{ foo:x }}

this

generator

function* fib(max){
    var t,
          a = 0,
          b = 1,
          n = 1;
    while(n<max){
        yield a;
        t = a + b;
        a = b;
        b = t;
        n++;
    }
    return a;
}

// 调用generator

// 方法1:使用next()
// done:false表示没有执行结束,true表示结束
// 当done是true时,`value`的值就是`return`的值
var f = fib(5);
f.next();  // Object {value: 0, done: false}
f.next();  // Object {value: 1, done: false}
f.next();  // Object {value: 1, done: false}
f.next();  // Object {value: 2, done: false}
f.next();  // Object {value: 3, done: true}

// done为true之后再使用next方法的话:
f.next();  // Object {value: undefined, done: true}

// 方法2:for...of循环迭代,不需要判断done
for (var x of fib(5)){
    console.log(x);
}

因为generator可以在执行过程中多次返回,所以它看上去就像一个可以记住执行状态的函数,利用这一点,写一个generator就可以实现需要用面向对象才能实现的功能。

generator还有另一个巨大的好处,就是把异步回调代码变成“同步”代码。

上一篇 下一篇

猜你喜欢

热点阅读