console.log("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);
值类型与引用类型
值类型: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));
="string"
vconsole.log(typeof(v));
}
if(1){
let person={
name:"gaowanlu",
age:11
;
}console.log(person.name);
console.log(person["name"]);
.phone="133466377";
personconsole.log(person);
console.log(person.phone);
let key="phone";
console.log(person[key]);
}
if(1){
let array=['red',1,'guy'];
console.log(array[0]);
0]="yellow";
array[console.log(array);
//得到数组长度
console.log(array.length);
}
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);
}
/*
Falsy(false)
undefined
null
0
false
''
NaN
*/
if(1){
console.log(1|2);//位或
console.log(1&2);//位或
}
(省略)
/*
因为与大多数编程风格一样(Python除外):省略
if(){
if(){
}
}else if(){
if(){
}else{
}
}else{
}
*/
/*
与C/C++相同
switch(){
case __:_________;break;
case __:_________;break;
default:—————————break;
}
*/
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
}=0;
ido{
++;
iwhile(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);
} }
省略
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);
.call();
personconsole.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,致命行为
.show();
cir }
if(1){
let person={
name:"gaowanlu"
;
}.phone="133";//添加属性
persondelete 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){
=person[key];
another[key]
}console.log(another);
//使用Object.assign()
= Object.assign({color:"yellow"},person);
anotherconsole.log(another);//{color: "yellow", name: "gaowanlu", age: 19}
//使用{...objname}
={...person};
another }
内存自动管理
if(1){
const message="gaowanlu";
常用方法
//concat()
let name="gaowanlu";
console.log(name.concat(" hello ","YES"));
模板语法
let show=`${name}fdfd${name}`;
.split()将字符串切为数组
let numbers="1 2 3 4 5 6";
=numbers.split(' ');
numbersconsole.log(numbers);//[1,2,3,4,5,6]
}
省略
Adding Elements 添加元素
if(1){
const numbers=[3,4,5];
//const数组我们不能修改,numbers但能修改数组的内部
.push()在后面添加新元素
.push(6,7,8);
numbersconsole.log(numbers);//[3,4,5,6,7,8]
.unshift()在前面添加新元素
.unshift(1,2);
numbersconsole.log(numbers);//[1, 2, 3, 4, 5, 6, 7, 8]
.splice()在中间插入新元素
.splice(2,0,'a','b');//从下标2开始,删除0个,插入a b
numbersconsole.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() 方法 返回第一个匹配的对象的下标
=course.findIndex(function(el){
foundreturn 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)
.splice(2,3);//从下标2开始删除后面3个元素
arrayconsole.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 清空
=[1,2,3];
numbers.length=0;
numbersconsole.log(numbers);
.splice(0,numbers.length) 清空
=[1,2,3];
numbers.splice(0,numbers.length); numbers
.pop()清空
=[1,2,3,4];
numberswhile(numbers.length>0){
.pop();
numbers
} }
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)切割数组
=[1,2,3,4,5,6,7,8,9];
array_1=array_1.slice(2,4);
array_1console.log(array_1);
[...__,...__] 拼接数组
=[1,2,3];
array_1=[4,5,6];
array_2console.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++){
=2*array[i];
array[i] }
.forEach(function)
.forEach(function(el){
arrayconsole.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() 方法
.sort();
numbers/*
[
1, 2, 2, 3,
5, 7, 8
]*/
console.log(numbers);
.reverse()方法 反转数组元素序列
.reverse();
numbersconsole.log(numbers);
/*[8, 7, 5, 3, 2, 2, 1]*/
数组根据对象属性排序
let courses=[
id:1,name:'gaowanlu'},
{id:2,name:'ming'}
{;
].sort(function(obj_a,obj_b){
coursesif(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
=[1,"ds"]; numbers
.some()
=numbers.some(function(el){
resultreturn typeof(el)=="string";
;
})console.log(result);//true
}
过滤数组元素
if(1){
.filter(function)
let numbers=[1,-1,2,3];
=numbers.filter(function(el){
numbersreturn 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.join("\n");
itemsconsole.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){
+=i;
sum
}return sum;
}console.log(sum(1,2,3,4,5));
//输出:15
余下操作符
=function(none,...args){
sumreturn args.reduce(function(sum,cur){
return sum+cur;
;
})
}console.log(sum(99,11,1,1));
//输出: 13
参数默认值
=function(a=1,b=1){
sumreturn a+b;
}console.log(sum());//输出: 2
}
if(1){
let obj={
count:0,
data:"",
get num(){
return num;
,
}set num(el){
this.data=el;
this.count+=1;
}
}.num=1;
obj.num=2;
objconsole.log(obj.count);//输出 2
}
if(1){
try{
throw new Error("new Error");
catch(err){
}
finally{
}
} }
this指向对象本身
//面向对象编程有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 }
//添加新属性或者方法
.show=function(){
circleconsole.log(this.center);
}.show();
circle//{ x: 1, y: 3 }
}
//工厂函数
if(1){
let factory=function(){
let obj={};
.show=function(){
objconsole.log("hello world");
}return obj;
}let new_obj=factory();
.show();
new_obj//hello world
}
//构造函数
if(1){
let constructor=function(){
this.show=function(){
console.log("hello world");
}
}let new_obj=new constructor();
.show();
new_obj//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] }
.data="gaowanlu";
new_objconsole.log(new_obj);
//{ show: [Function: show], data: 'gaowanlu' }
"id"]=1234;
new_obj[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(){
+=1;
dataconsole.log(data);
};
}let new_obj=new Circle();
.show();
new_obj.show();
new_obj.show();
new_obj/*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();
.data="qw";
new_obj//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,//不可配置(可不可删去)
;
}).name="opp";
persondelete 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的父类添加方法
.prototype.draw=function(){
Carconsole.log("draw");
}let car_1=new Car();
let car_2=new Car();
.draw();
car_1.draw();
car_2//draw draw
}
//子类父类方法可以互相调用
if(1){
let Cir=function(){
this.draw=function(){
console.log("draw");
//this.move();
}
}.prototype.move=function(){
Circonsole.log("move");
this.draw();
}let new_obj=new Cir();
.move();
new_obj//move draw
}
//继承不等于拥有
//继承的是父级的引用,自然父级改变,子级继承的也会改变
//Object.keys()返回对象实体成员
//for in 所有成员、包括继承的东西
if(1){
let Cir=function(){
this.data=123;
;
}.prototype.name="gaowanlu";
Cirlet 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";
;
}.prototype.show=function(){
Teslaconsole.log(this.type);
}let Audi=function(){
this.type="Audi";
;
}.prototype.show=function(){//show属于类
Audiconsole.log(this.type);
}let car_1=new Tesla();
let car_2=new Audi();
.show();//Tesla
car_1.show();//Audi
car_2//我们会发现又出现问题了,这两个方法不是一样吗,能不能用一个来表示
console.log(car_1);
console.log(car_2);
//使用继承
=function(){
Teslathis.type="tesla"
;
}.prototype.show=function(){
Teslaconsole.log(this.type);
}=function(){
Audithis.type="audi";
;
}//让Audi使用和Tesla一样的prototype
//Object.create()会返回一个和Tesla.prototype一样的对象
.prototype=Object.create(Tesla.prototype);
Audi//此时Audi.prototype内的constructor是Tesla的构造函数,我们要更改过来
.prototype.constructor=Audi;
Audi//现在可以使用
let nice_car=new Audi();
.show();//输出audi
nice_car
}
//要记住继承的是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){
.call(this,color);//调用父对象构造函数
CarColorthis.type="Tesla";
;
}let car=new Tesla("red");
console.log(car);
//输出 Tesla { color: 'red', type: 'Tesla' }
}
//方法重写(Method Overriding)
//在子类中重写一个基类定义的方法
if(1){
let extend=function(child,parent){
.prototype=Object.create(parent.prototype);
child.prototype.constructor=child;
child
}let CarColor=function(color){
this.color=color;
;
}.prototype.ShowColor=function(){
CarColorconsole.log("red");
}let Tesla=function(color){
.call(this,color);
CarColorthis.type="tesla";
;
}extend(Tesla,CarColor);
let my_car=new Tesla("blue");
.ShowColor();
my_car//输出"red"
//这不是我们想要的方法怎么办,方法重写
//重写需要在继承之后
.prototype.ShowColor=function(){
Teslaconsole.log(this.color);
;
}=new Tesla("yellow");
my_car.ShowColor();
my_car//yes!!输出了 yellow
}
//多态
//一个多个子类继承一个父类的同一个方法
//但在,两个子类中使用有不同的效果
if(1){
let extend=function(child,parent){
.prototype=Object.create(parent.prototype);
child.prototype.constructor=child;
child;
}let CarColor=function(){
this.color="red";
;
}.prototype.ShowColor=function(){
CarColorconsole.log("red");
;
}let Tesla=function(color){
this.type="tesla",
.call(this,color);
CarColor;
}extend(Tesla,CarColor);
.prototype.ShowColor=function(){
Teslaconsole.log("blue tesla");
;
}let Audi=function(color){
.call(this,color);
CarColorthis.type="audi";
;
}extend(Audi,CarColor);
.prototype.ShowColor=function(){
Audiconsole.log("black audi");
;
}let array=[new Tesla(),new Audi()];
for(let car of array){//多态的好处
.ShowColor();
car
}/*输出
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(){
};
}.parse();//ff中有parse()
fflet 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(){
.set(this,123456);
_name.set(this,function(){
_shownameconsole.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函数式编程基础*/
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.map(number=>number*2);
nnjfdconsole.log(nnjfd);//[2,4,6]
//箭头函数,与流水线化
="JS";
input=str=>str.trim();
trim=str=>`<div>${str}</div>`;
wrapInDiv=str=>str.toLowerCase();
toLowerCase=wrapInDiv(toLowerCase(trim(input)));
resultconsole.log(result);//<div>js</div>
//当wrapInDiv(toLowerCase(trim(input)));功能越多,代码越来越多
//比较乱,怎么解决看起来好一些呢
let fp=require("lodash/fp");
=fp.compose(wrapInDiv,toLowerCase,trim);//何为一个函数,从右到左执行
transform//每个函数的返回值会成为下个函数的参数
console.log(transform(input));//<div>js</div>
=fp.pipe(trim,toLowerCase,wrapInDiv);//何为一个函数,从左到右执行
transformconsole.log(transform(input));//<div>js</div>
//柯里化
=str=>str.trim();
trim=type=>str=>`<${type}>${str}<${type}>`;
wrapInDiv/*
function(a){
return function(b){
return a+b;
}
}
*/
=str=>str.toLowerCase();
toLowerCase=fp.pipe(trim,toLowerCase,wrapInDiv("div"));
transformconsole.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'}};
.name='Mary';
person//Error person={}
=Object.assign({},person,{name:'Bob',age:11});//将person对象内的内容复制到{} 再返回
tempObjectconsole.log(tempObject);//{ name: 'Bob', adress: { city: 'san francisco' }, age: 11 }
//拆分操作符
={...person,a:'a',b:'b'};
tempObjectconsole.log(tempObject);//{ name: 'Mary', adress: { city: 'san francisco' }, a: 'a', b: 'b' }
.adress.city='ppp';
tempObjectconsole.log(person);//{ name: 'Mary', adress: { city: 'ppp' } }
//上面对象的拷贝都只是一种浅拷贝,拆分操作符与Object.assign都是
//如何深拷贝,手动使用...将adress拆分,重写city
={...person,adress:{...person.adress,city:'p'}};
tempObject.adress.city='ccc';
tempObjectconsole.log(tempObject);//{ name: 'Mary', adress: { city: 'ccc' } }
console.log(person);//{ name: 'Mary', adress: { city: 'ppp' } };
//或者使用深拷贝库来解决问题
//更新数组
=[1,2,3];
numbers=numbers.indexOf(2);
index//Adding
=[
added...numbers.slice(0,index),
4,
...numbers.slice(index)
;
]console.log(added);//[ 1, 4, 2, 3 ]
//Removing
=numbers.filter(n=>{
numbersreturn n!==4;
;
})console.log(numbers);//[1,2,3]
//Updating
=numbers.map(v=>{return v===2?20:v});
updatedconsole.log(updated);//[ 1, 20, 3 ]
//不可变对象immutable库
const { Map } = require('immutable');
let book=Map({title:"Harry Potter"});
function publish(book){
return book.set("isPublished",true);
}=publish(book);
bookedconsole.log(book.toJS());//{ title: 'Harry Potter' }
console.log(booked.toJS());//{ title: 'Harry Potter', isPublished: true }
={title:"Harry Potter"};
bookconst {produce}=require("immer");
function publish1(book){
return produce(book,draftBook=>{
.isPublished=true;
draftBook;
})
}=publish1(book);
tempconsole.log(book);//{ title: 'Harry Potter' }
console.log(temp);//{ title: 'Harry Potter', isPublished: true }
.title='OOPOP';
tempconsole.log(book);//{ title: 'Harry Potter' }
console.log(temp);//{ title: 'Harry Potter', isPublished: true }