JavaScript语法快速学习

JavaScript看这个就够了-入门基础篇

打印你的第一个hello world

变量

在ES6出现之前使用var来定义变量,但var定义变量作用域是全局的,对于编程语言来说这是比较不规范的。

if(1){
    var i=0;
}
console.log(i);

对于C++这样的静态语言,则会报错i没有定义,在javascript中则是输出了0,而我们使用let定义变量。

if(1){
    let uselet=0;
}
//console.log(uselet);
//Uncaught ReferenceError: uselet is not defined
//则会产生异常

可见我们能使用let 就不要使用 var

定义常量(不过多阐述对有编程基础的学习者)

const num=1000;
//num=999;
//Uncaught TypeError: Assignment to constant variable.
console.log("num:",num);

JavaScript两种类型变量

值类型与引用类型 值类型:String Number Boolean undefined null 引用类型:Object Array Function

if(1){
    //String
    let name="gaowanlu";
    //Number
    let m=30;
    //Boolean
    let k=true;
    //undefined
    let u=undefined;
    //null
    let n=null;    
}

编程语言有两种:动态语言 静态语言

JavaScript属于前者,也就是说我们定义了变量,什么时候想改变它的数据类型就可以改变。

在C++中、一旦编码 int variable=1; 我们就无法把variable当float使用 在Javascript中 let i="javascript"; i=10; 这是完全可行的操作

if(1){
    let v=1;
    console.log(typeof(v));
    v="string"
    console.log(typeof(v));
}

JavaScript一切皆对象

Object

if(1){
    let person={
        name:"gaowanlu",
        age:11
    };
    console.log(person.name);
    console.log(person["name"]);
    person.phone="133466377";
    console.log(person);
    console.log(person.phone);
    let key="phone";
    console.log(person[key]);
}

Array

if(1){
    let array=['red',1,'guy'];
    console.log(array[0]);
    array[0]="yellow";
    console.log(array);
    //得到数组长度
    console.log(array.length);
}

Function

if(1){
    function hello(name){
        if(typeof(name)=="string"){
            console.log(name+"  hello.");  
            return true;          
        }else{
            return false;
        }
    }
    hello("gaowanlu");
}

操作符、运算符(不详细介绍、这是编程很基础的东西)

/*
+ - * / 加减乘除
= 赋值
+= -= *= /= 加减乘除
% 取余
** 指数
++ -- 自加1 自减1
> >= < <= != == === 比较运算符
&& || ! 与 或 非
*/

三元运算符

if(1){
    let output=2>1?"2>1":"2<1";
    console.log(output);
}

JavaScript中的类假值

/*
Falsy(false)
undefined
null
0
false
''
NaN
*/

位运算符

if(1){
    console.log(1|2);//位或
    console.log(1&2);//位或
}

运算符优先级

(省略)

if语句

/*
因为与大多数编程风格一样(Python除外):省略
if(){
    if(){

    }
}else if(){
    if(){

    }else{

    }
}else{

}
*/

switch case语句

/*
与C/C++相同
switch(){
    case __:_________;break;
    case __:_________;break;
    default:—————————break;
}
*/

JavaScript 循环

for 、 while、 do while、 for in、 for of

if(1){
    for(let i=0;i<5;i++){
        console.log(i);
    }
    let i=0;
    while(i<5){
        i++;
    }
    i=0;
    do{
        i++;
    }while(i<5);
}
if(1){
    let person={
        name:"gaowanlu",
        age:19
    };
    for(let key in person){
        console.log(key," : ",person[key]);
    }
    let colors=['red','green','blue'];
    for(let index in colors){
        console.log(colors[index]);
    }
    for(let val of colors){
        console.log(val);
    }
}

break 与 continue

省略

详细学习Object

if(1){
    let person={
        name:"gaowanlu",
        phone:"133466377",
        call:function(){
            console.log(this.name,this.phone);
            this.class_sum+=1;
        },
        class_sum:0,
    };
    console.log(person);
    person.call();
    console.log(person);
}

工厂函数

function create_obj(){
    let person={
        name:"gaowanlu",
        phone:"133466377",
        call(){//call()是class:function()的缩写
            console.log(this.name,this.phone);
            this.class_sum+=1;
        },
        class_sum:0,
    };
    return person;
}
if(1){
    let obj=create_obj();
    console.log(obj);
}

构造函数(函数即对象)

function Circle(radius){
    this.radius=radius;
    this.show=function(){
        console.log(this.radius);
    }
}
if(1){
    let cir=new Circle(10);
    //如果没写new那么Circle内的this指向window,致命行为
    cir.show();
}

对象动态性

if(1){
let person={
    name:"gaowanlu"
};
person.phone="133";//添加属性
delete person.name;//删除属性或者方法
console.log(person);
}

枚举对象成员

if(1){
    let person={
        name:"gaowanlu",
        age:19
    };
    for(let key in person){
        console.log(person[key]);
    }
    for(let key of Object.keys(person)){
        console.log(person[key]);
    }
    for(let entry of Object.entries(person)){
        console.log(entry);
    }
    /*
    Object.entries(person)=
    [["name", "gaowanlu"],["age", 19]]
    */
}

克隆对象

if(1){
    let person={
        name:"gaowanlu",
        age:19
    };
    let another={};
    for(let key in person){
        another[key]=person[key];
    }
    console.log(another);

    //使用Object.assign()
   another= Object.assign({color:"yellow"},person);
   console.log(another);//{color: "yellow", name: "gaowanlu", age: 19}

   //使用{...objname}
   another={...person};
}

垃圾回收

内存自动管理

Math对象

String对象

if(1){
    const message="gaowanlu";
    //concat()
    let name="gaowanlu";
    console.log(name.concat(" hello ","YES"));
    let show=`${name}fdfd${name}`;
    let numbers="1 2 3 4 5 6";
    numbers=numbers.split(' ');
    console.log(numbers);//[1,2,3,4,5,6]
}

Date对象

省略

Array对象

Adding Elements 添加元素

if(1){
    const numbers=[3,4,5];
    //const数组我们不能修改,numbers但能修改数组的内部

.push()在后面添加新元素

    numbers.push(6,7,8);
    console.log(numbers);//[3,4,5,6,7,8]

.unshift()在前面添加新元素

    numbers.unshift(1,2);
    console.log(numbers);//[1, 2, 3, 4, 5, 6, 7, 8]

.splice()在中间插入新元素

    numbers.splice(2,0,'a','b');//从下标2开始,删除0个,插入a b
    console.log(numbers);//[1, 2, "a", "b", 3, 4, 5, 6, 7, 8]
    // .splice()第一个参数是插入位置下标,第二个参数删除几个元素,后面为新元素
}

Finding Elements(Primitives)查找元素(值类型)

if(1){
    const numbers=[1,2,3,4,5,1,2,3,4,5];

.indexOf(el,start)查找第一个符合要求的元素

    console.log(numbers.indexOf(5));//start为从那个下标开始查找
    /* 4  即第一个符合要求的元素的下标,找不到返回-1 */

.lastIndexOf()查找最后一个符合要求的元素

    console.log(numbers.lastIndexOf(5));
    /* 输出:     9        */

.includes() 检查数组中有没有某个元素返回布尔值

    console.log(numbers.includes(1));
}

Finding Elements(Object)查找元素(对象)

if(1){
    const course=[
        {id:1,name:'a'},
        {id:2,name:'b'}
    ];

.find() 方法 返回第一个匹配的对象

    var found=course.find(function(el){
        return el.id==1&&el.name=='a';
    });
    console.log(found);
    //{id: 1, name: "a"}

.findIndex() 方法 返回第一个匹配的对象的下标

    found=course.findIndex(function(el){
        return el.id==1;
    });
    console.log(found);//输出:0
}

箭头函数

if(1){
    const courses=[
        {id:1,name:'a'},
        {id:2,name:'b'}
    ];
    const course=courses.find((el)=>{
        return el.name==='a';
    });
    /*
    (参数列表)=>{函数体},当只有一个参数是可以写为
    参数列表=>{函数体}
    */
    console.log(course);
}

Removing Elements(删除元素)

if(1){
    const array=[1,2,3,4,5,6,7,8,9];

.splice(index,count)

    array.splice(2,3);//从下标2开始删除后面3个元素
    console.log(array);//[1,2,6,7,8,9]

Emptying an Array(清空数组)

if(1){
    let numbers=[1,2,3,4];
    console.log(numbers);

=[] 赋值清空

    numbers=[];

.length=0 清空

    numbers=[1,2,3];
    numbers.length=0;
    console.log(numbers);

.splice(0,numbers.length) 清空

    numbers=[1,2,3];
    numbers.splice(0,numbers.length);

.pop()清空

    numbers=[1,2,3,4];
    while(numbers.length>0){
        numbers.pop();
    }
}

Combining Arrays(组合和切割数组)

if(1){

.concat() 数组合并

    let array_1=[1,2,3];
    let array_2=[4,5,6];
    let array_concat=array_1.concat(array_2);
    console.log(array_concat);
    //[ 1, 2, 3, 4, 5, 6 ]

.slice(start_index,end_index_after)切割数组

    array_1=[1,2,3,4,5,6,7,8,9];
    array_1=array_1.slice(2,4);
    console.log(array_1);

[...__,...__] 拼接数组

    array_1=[1,2,3];
    array_2=[4,5,6];
    console.log([...array_1,"a",...array_2]);
    //[ 1, 2, 3, 'a', 4, 5, 6]
}

遍历数组

if(1){
    let array=[1,2,3,4,5,6,7,8,9];

传统for循环

    for(let i=0;i<array.length;i++){
        array[i]=2*array[i];
    }

.forEach(function)

    array.forEach(function(el){
        console.log(el);
    });

}

Joining Arrays(连接数组元素)

if(1){
    let numbers=[1,2,3];
    let string=numbers.join(",");
    console.log(string);//1,2,3
}

Sorting Arrays(数组排序)

if(1){
    let numbers=[1,2,5,3,2,7,8];

.sort() 方法

    numbers.sort();
    /*
    [
        1, 2, 2, 3,
        5, 7, 8
    ]*/
    console.log(numbers);

.reverse()方法 反转数组元素序列

    numbers.reverse();
    console.log(numbers);
    /*[8, 7, 5, 3, 2, 2, 1]*/

数组根据对象属性排序

    let courses=[
        {id:1,name:'gaowanlu'},
        {id:2,name:'ming'}
    ];
    courses.sort(function(obj_a,obj_b){
        if(obj_a.id<obj_b.id) return 1;
        if(obj_a.id>obj_b.id) return -1;
        return 0;
    });
    console.log(courses);
    //[ { id: 2, name: 'ming' }, { id: 1, name: 'gaowanlu' } ]
}

检测数组中的元素

if(1){
    let numbers=[1,2,3];

.every()

    let result=numbers.every(function(el){//全部都是数组返回true
        return typeof(el)=="number";
    });
    console.log(result);//true
    numbers=[1,"ds"];

.some()

    result=numbers.some(function(el){
        return typeof(el)=="string";
    });
    console.log(result);//true
}

过滤数组元素

if(1){

.filter(function)

    let numbers=[1,-1,2,3];
    numbers=numbers.filter(function(el){
        return el>=0;
    });
    console.log(numbers);//[ 1, 2, 3 ]
}

数组映射

if(1){
    let numbers=[1,-1,2,3];

.map()

    let items=numbers.map(function(el){
        return `'<li>'+el.toString()+'</li>';`
    });
    console.log(items);
    //`[ '<li>1</li>', '<li>-1</li>', '<li>2</li>', '<li>3</li>' ]`
    items=items.join("\n");
    console.log(items);
    /*`
    <li>1</li>
    <li>-1</li>
    <li>2</li>
    <li>3</li>
    `*/
}

缩减数组

if(1){

.reduce() 方法

    let numbers=[1,2,3,4,5,6];
    let sum=numbers.reduce(function(sum,cur){
        return sum+cur;
    });
    console.log(sum);
    //21
}

函数表达式与函数声明

if(1){
    function SuperCar(){
        console.log("Tesla");
    }
    let tesla=function(){
        console.log("Tesla");
    }
}

深入函数参数

if(1){ 使用arguments

    let sum=function(a,b){
        let sum=0;
        for(let i of arguments){
            sum+=i;
        }
        return sum;
    }
    console.log(sum(1,2,3,4,5));
    //输出:15

余下操作符

    sum=function(none,...args){
        return args.reduce(function(sum,cur){
            return sum+cur;
        });
    }
    console.log(sum(99,11,1,1));
    //输出: 13

参数默认值

    sum=function(a=1,b=1){
        return a+b;
    }
    console.log(sum());//输出: 2

}

getters and setters 取存器

if(1){
    let obj={
        count:0,
        data:"",
        get num(){
            return num;
        },
        set num(el){
            this.data=el;
            this.count+=1;
        }
    }
    obj.num=1;
    obj.num=2;
    console.log(obj.count);//输出 2
}

异常

if(1){
    try{
        throw new Error("new Error");
    }catch(err){
        
    }finally{

    }
}

this

this指向对象本身

JavaScript看这个就够了-面向对象篇

//面向对象编程有4个概念
//封装、抽象、继承和多态
//Encapsulation Abstraction Inheritance Polymorphism

/*
使用封装重新组合相关的变量和函数
这样我们可以减少复杂性、我们可以在程序的不同部分重用这些对象
或者在不同的程序中

通过抽象,我们隐藏细节和复杂性
只显示必要的部分
这种技术降低了复杂性、也隔离了代码的更改的影响

继承让我们可以消除多余的代码

用多态性我们可以避免写出复杂丑陋的选择性代码
*/

//Object 
/*
JavaScript一切皆是对象
*/

//对象创建语法
//是一种简单的定义对象的方法
if(1){
    let circle={
        center:{
            x:1,
            y:3
        },
        radius:10,
    };
    console.log(circle);
    //{ center: { x: 1, y: 3 }, radius: 10 }
    //添加新属性或者方法
    circle.show=function(){
        console.log(this.center);
    }
    circle.show();
    //{ x: 1, y: 3 }
}


//工厂函数
if(1){
    let factory=function(){
        let obj={};
        obj.show=function(){
            console.log("hello world");
        }
        return obj;
    }
    let new_obj=factory();
    new_obj.show();
    //hello world
}


//构造函数
if(1){
    let constructor=function(){
        this.show=function(){
            console.log("hello world");
        }
    }
    let new_obj=new constructor();
    new_obj.show();
    //hello world
}

//构造函数属性(Constructor Property)
/*
每个javascript中的对象都有一个叫构造函数的属性
它是一个用于创建这个对象的构造方法的引用
*/
if(1){
    let circle=function(){
        return {
            show:function(){
                console.log("hello world");
            }
        }
    };
    let new_obj=circle();
    console.log(new_obj.constructor);
}

//添加删除属性(Adding/Removing Properties)
if(1){
    let circle=function(){
        return{
            show:function(){
                console.log("hello world");
            }
        }
    };
    let new_obj=circle();
    console.log(new_obj);
    //{ show: [Function: show] }
    new_obj.data="gaowanlu";
    console.log(new_obj);
    //{ show: [Function: show], data: 'gaowanlu' }
    new_obj["id"]=1234;
    console.log(new_obj);
    //{ show: [Function: show], data: 'gaowanlu', id: 1234 }
    delete new_obj["show"];
    console.log(new_obj);
    //{ data: 'gaowanlu', id: 1234 }
}



//遍历或枚举对象
if(1){
    let obj={
        id:"gaowanlu",phone:"1234"
    };
    for(let i in obj){
        console.log(obj[i]);
    }
    //1234
}

//Hide the details Show the essentials
/*
抽象意味着我们应该隐藏细节和复杂的部分,只显示或暴露必要的部分
*/


//私有属性与方法
if(1){
    let Circle=function(){
        //@private
        let data=0;
        //@public
        this.show=function(){
            data+=1;
            console.log(data);
        }
    };
    let new_obj=new Circle();
    new_obj.show();
    new_obj.show();
    new_obj.show();
    /*1 2 3*/
}


//Getters/Setters defineProperties
if(1){
    let Circle=function(){
        let new_obj={};
        Object.defineProperty(new_obj,"data",{
            get:function(){
                return "hello";
            },
            set:function(el){
                console.log(el);
            }
        });
        return new_obj;
    };
    let new_obj=Circle();
    new_obj.data="qw";
    //qw
    console.log(new_obj.data);
    //hello
}


//继承(inheritance)
//不同的类需要相同的属性或方法,使用继承解决
if(1){
    let Circle=function(radius){
        this.radius=radius;
        this.draw=function(){
            console.log('draw');
        };
    }
    let circle= new Circle(2);
    console.log(circle.__proto__.__proto__);
    //{}
}


//Object.defineProperty()
if(1){
    let person={name:"gaowanlu"};
    Object.defineProperty(person,"name",{
        writable:false,//不可写
        enumerable:true,//可枚举
        configurable:false,//不可配置(可不可删去)
    });
    person.name="opp";
    delete person.name;
    console.log(person);
}

//原型继承
if(1){
    let Circle=function(){
        this.draw=function(){
            console.log('draw');
        }
    };
    let circle_1=new Circle();
    let circle_2=new Circle();
    //circle_1 circle_2内都有一个实体的方法draw
    //占用两个内存空间,如果Circle对象多了起来怎么办
    let Car=function(){
        this.money=1000000;
    };
    //给Car的父类添加方法
    Car.prototype.draw=function(){
        console.log("draw");
    }
    let car_1=new Car();
    let car_2=new Car();
    car_1.draw();
    car_2.draw();
    //draw draw
}


//子类父类方法可以互相调用
if(1){
    let Cir=function(){
        this.draw=function(){
            console.log("draw");
            //this.move();
        }
    }
    Cir.prototype.move=function(){
        console.log("move");
        this.draw();
    }
    let new_obj=new Cir();
    new_obj.move();
    //move draw
}

//继承不等于拥有
//继承的是父级的引用,自然父级改变,子级继承的也会改变

//Object.keys()返回对象实体成员
//for in 所有成员、包括继承的东西
if(1){
    let Cir=function(){
        this.data=123;
    };
    Cir.prototype.name="gaowanlu";
    let new_obj=new Cir();
    console.log(Object.keys(new_obj));
    //[ 'data' ]
    for(let key in new_obj){
        console.log(key);
    }
    //data
    //name
    //判断是不是对象内的实体
    console.log(new_obj.hasOwnProperty("data"));//true
    console.log(new_obj.hasOwnProperty("name"));//false
}


//创建自己的原型继承
if(1){
    let Tesla=function(){
        this.type="Tesla";
    };
    Tesla.prototype.show=function(){
        console.log(this.type);
    }
    let Audi=function(){
        this.type="Audi";
    };
    Audi.prototype.show=function(){//show属于类
        console.log(this.type);
    }
    let car_1=new Tesla();
    let car_2=new Audi();
    car_1.show();//Tesla
    car_2.show();//Audi
    //我们会发现又出现问题了,这两个方法不是一样吗,能不能用一个来表示
    console.log(car_1);
    console.log(car_2);

    //使用继承
    Tesla=function(){
        this.type="tesla"
    };
    Tesla.prototype.show=function(){
        console.log(this.type);
    }
    Audi=function(){
        this.type="audi";
    };
    //让Audi使用和Tesla一样的prototype
    //Object.create()会返回一个和Tesla.prototype一样的对象
    Audi.prototype=Object.create(Tesla.prototype);
    //此时Audi.prototype内的constructor是Tesla的构造函数,我们要更改过来
    Audi.prototype.constructor=Audi;
    //现在可以使用
    let nice_car=new Audi();
    nice_car.show();//输出audi
}

//要记住继承的是prototype对象内的内容而不是自己定义的对象属性与方法
//上面show方法属于prototype type属性属于对象,type不可以继承


//每个对象的构造函数为class.prototype.constructor()
//let cir=new Circle(1);
//等价于 let cir=new class.prototype.constructor(1);
//prototype就是__prototype__



//使用父对象构造函数
if(1){
    let CarColor=function(color){
        this.color=color;
    }
    let Tesla=function(color){
        CarColor.call(this,color);//调用父对象构造函数
        this.type="Tesla";
    };
    let car=new Tesla("red");
    console.log(car);
    //输出 Tesla { color: 'red', type: 'Tesla' }
}


//方法重写(Method Overriding)
//在子类中重写一个基类定义的方法
if(1){
    let extend=function(child,parent){
        child.prototype=Object.create(parent.prototype);
        child.prototype.constructor=child;
    }
    let CarColor=function(color){
        this.color=color;
    };
    CarColor.prototype.ShowColor=function(){
        console.log("red");
    }
    let Tesla=function(color){
        CarColor.call(this,color);
        this.type="tesla";
    };
    extend(Tesla,CarColor);
    let my_car=new Tesla("blue");
    my_car.ShowColor();
    //输出"red"
    //这不是我们想要的方法怎么办,方法重写
    //重写需要在继承之后
    Tesla.prototype.ShowColor=function(){
        console.log(this.color);
    };
    my_car=new Tesla("yellow");
    my_car.ShowColor();
    //yes!!输出了 yellow
}



//多态
//一个多个子类继承一个父类的同一个方法
//但在,两个子类中使用有不同的效果
if(1){
    let extend=function(child,parent){
        child.prototype=Object.create(parent.prototype);
        child.prototype.constructor=child;
    };
    let CarColor=function(){
        this.color="red";
    };
    CarColor.prototype.ShowColor=function(){
        console.log("red");
    };
    let Tesla=function(color){
        this.type="tesla",
        CarColor.call(this,color);
    };
    extend(Tesla,CarColor);
    Tesla.prototype.ShowColor=function(){
        console.log("blue tesla");
    };
    let Audi=function(color){
        CarColor.call(this,color);
        this.type="audi";
    };
    extend(Audi,CarColor);
    Audi.prototype.ShowColor=function(){
        console.log("black audi");
    };
    let array=[new Tesla(),new Audi()];
    for(let car of array){//多态的好处
        car.ShowColor();
    }
    /*输出
    blue tesla
    black audi*/
}


//谨慎使用继承,不会用就避免使用


//ES6 Classes相关语法
if(1){
    //之前Tesla构造函数
    let Tesla=function(color){
        this.color=color;
        this.speed="299km/s";
        this.type="tesla";
        this.showUser=function(){
            console.log("gaowanlu");
        };
    };
    //采用ES6语法写
    class Tesla_class{
        constructor(color){//构造函数
            this.color=color;
            this.speed="299km/s";
            this.type="tesla";
        }
        //在构造函数constructor外写的东西属于prototype的内容
        showUser(){
            console.log("gaowanlu");
        }
    }
    let car = new Tesla_class("red");
    console.log(car);
    //输出 Tesla_class { color: 'red', speed: '299km/s', type: 'tesla' }
    console.log(typeof(Tesla_class));
    //输出 function
    //class只是皮,肉是function

    //Hoisting
    //两种声明class方式
    if(1){
        class via{
        }
        const yiu=class{
        }
    }

    //static Methods(静态方法:只在类中有效)
    let ff=class{
        constructor(){
        }
        draw(){
        }
        static parse(){
        }
    };
    ff.parse();//ff中有parse()
    let obj=new ff();
    //obj.parse(); obj中没有parse()



    //对象私有成员
    const _draw=Symbol();
    let lua=class{
        constructor(){
        }
        [_draw](){
            console.log("私有");
        }
    };
    //外部无法使用[_draw]()


    //弱映射
    const _name=new WeakMap();
    const _showname=new WeakMap();
    let didi=class{
        constructor(){
            _name.set(this,123456);
            _showname.set(this,function(){
                console.log("_showname");
            });
        }
        get radius(){
            return 1;
        }
        set radius(el){
            console.log(el);
        }
    }
}

//ES6 继承
if(1){
    class TeslaColor{
        constructor(color){
            this.color=color;
        }
        ShowColor(){
            console.log(this.color);
        }
    };
    class TTCar extends TeslaColor{
        constructor(color){
            super(color);//调用TeslaColor构造函数
        }
    }
}


//ES6 方法重写
if(1){
    class GaoF{
        move(){
            console.log("GaoF");
        }
    }
    class Fu extends GaoF{
        move(){//直接重写

        }
    }
}

javascript函数式编程基础

函数调用 引用 做返回值

/*javascript函数式编程基础*/
function sayHello(){
    return "hello world";
}
let result=sayHello();//函数调用
let fn=sayHello;//函数引用
console.log(fn());//hello world

//函数做返回值
function ee(){
    return function(){
        return "hello world";
    }
}
console.log(ee()());//hello world

高阶函数,传入参数为函数


//高阶函数,传入参数为函数
let nnjfd=[1,2,3];
nnjfd=nnjfd.map(number=>number*2);
console.log(nnjfd);//[2,4,6]

箭头函数与函数功能流水线化

//箭头函数,与流水线化
input="JS";
trim=str=>str.trim();
wrapInDiv=str=>`<div>${str}</div>`;
toLowerCase=str=>str.toLowerCase();
result=wrapInDiv(toLowerCase(trim(input)));
console.log(result);//<div>js</div>
//当wrapInDiv(toLowerCase(trim(input)));功能越多,代码越来越多
//比较乱,怎么解决看起来好一些呢
let fp=require("lodash/fp");
transform=fp.compose(wrapInDiv,toLowerCase,trim);//何为一个函数,从右到左执行
//每个函数的返回值会成为下个函数的参数
console.log(transform(input));//<div>js</div>
transform=fp.pipe(trim,toLowerCase,wrapInDiv);//何为一个函数,从左到右执行
console.log(transform(input));//<div>js</div>

柯里化


//柯里化
trim=str=>str.trim();
wrapInDiv=type=>str=>`<${type}>${str}<${type}>`;
/*
function(a){
    return function(b){
        return a+b;
    }
}
*/
toLowerCase=str=>str.toLowerCase();
transform=fp.pipe(trim,toLowerCase,wrapInDiv("div"));
console.log(transform(input));//<div>js<div>

纯函数

//纯函数
//纯函数中不能使用随机值
//No random values
//no current date/time
//no global state
function isEligible(age){//it's not pure function
    return age>minAge;
}
function isEligi(age,minAge){//it's pure function
    return age>minAge;
}
//纯函数优点
/*Self-documenting  Easily testable  Concurrency  Cacheable*/

更新对象、浅拷贝问题

//更新对象
const person={name:'John',adress:{city:'san francisco'}};
person.name='Mary';
//Error  person={}
tempObject=Object.assign({},person,{name:'Bob',age:11});//将person对象内的内容复制到{} 再返回
console.log(tempObject);//{ name: 'Bob', adress: { city: 'san francisco' }, age: 11 }
//拆分操作符
tempObject={...person,a:'a',b:'b'};
console.log(tempObject);//{ name: 'Mary', adress: { city: 'san francisco' }, a: 'a', b: 'b' }
tempObject.adress.city='ppp';
console.log(person);//{ name: 'Mary', adress: { city: 'ppp' } }
//上面对象的拷贝都只是一种浅拷贝,拆分操作符与Object.assign都是
//如何深拷贝,手动使用...将adress拆分,重写city
tempObject={...person,adress:{...person.adress,city:'p'}};
tempObject.adress.city='ccc';
console.log(tempObject);//{ name: 'Mary', adress: { city: 'ccc' } }
console.log(person);//{ name: 'Mary', adress: { city: 'ppp' } };
//或者使用深拷贝库来解决问题

更新数组

//更新数组
numbers=[1,2,3];
index=numbers.indexOf(2);
//Adding
added=[
    ...numbers.slice(0,index),
    4,
    ...numbers.slice(index)
];
console.log(added);//[ 1, 4, 2, 3 ]
//Removing
numbers=numbers.filter(n=>{
    return n!==4;
});
console.log(numbers);//[1,2,3]
//Updating
updated=numbers.map(v=>{return v===2?20:v});
console.log(updated);//[ 1, 20, 3 ]

不可变对象 immutable与immer库


//不可变对象immutable库
const { Map } = require('immutable');
let book=Map({title:"Harry Potter"});
function publish(book){
    return book.set("isPublished",true);
}
booked=publish(book);
console.log(book.toJS());//{ title: 'Harry Potter' }
console.log(booked.toJS());//{ title: 'Harry Potter', isPublished: true }

book={title:"Harry Potter"};
const {produce}=require("immer");
function publish1(book){
    return produce(book,draftBook=>{
        draftBook.isPublished=true;
    });
}
temp=publish1(book);
console.log(book);//{ title: 'Harry Potter' }
console.log(temp);//{ title: 'Harry Potter', isPublished: true }
temp.title='OOPOP';
console.log(book);//{ title: 'Harry Potter' }
console.log(temp);//{ title: 'Harry Potter', isPublished: true }