JS知识:变量,赋值,拷贝,参数传递

Mutable vs. Immutable

immutable

immutable 变量是不可变变量/原始变量,它一旦创建,在整个生命周期内都是不可以改变的。在JavaScript中只有以下几种变量是不可变变量:字符串, 数字,boolean,其它所有变量都是可变变量。

let a = "this is a string";   
let b = a.slice(0,4);
//a没有变化,就是不可变变量,string 有concat函数,并非改变原来的string的生命周期。

要注意的是,仅当直接赋值时才是immutable状态,如果使用new的方式创建字符串或数字,则创建的是对象而不是原始变量,它是可变的。

let a = 3; // immutable
typeof a; // number

let b = new Number(4); // mutable  new String("s")  new Boolean
typeof b; // object
mutable

在JavaScript中,除了原始变量之外的所有变量都是可变变量:对象、数组。

const people = {
    title: "student",
    age: 14
}
people.age = 20;
console.log(people);
//跟前面的不可变变量相反,它是可以直接修改对象的属性

两者区别
Mutable是对象,如果引用另一个对象,当前对象属性变化,也会影响到被引用的对象。Imutable 则是原始变量。
对React.js的影响
当我们对React的state进行修改时,如果变量是一个mutable变量,那么就不能直接修改,需要把它转换成另外一个变量才能触发render更新。例如:

this.state; // {a: {b: 'test'}}
const a = this.state.a;
a.b = 'test2';
this.setState({a});

这是不会触发render的更新,要改成:

const a = JSON.parse(JSON.stringfy(this.state.a));
a.b = 'test2';
this.setState({a});

这是因为当setState赋值给a时,如果a仍然是之前state里的a(指针相同),那么react就认为state没有更新,于是就不会去更新view,但如果通过JSON转换之后,这个a指向的内存地址发生变化,不再是以前的a,react就能发现state的变化,于是就会去更新view。
! The JSON.parse() method parses a JSON string, constructing the JavaScript value or object described by the string.

deep copy, shadow copy

赋值相当于给一个变量传一个新的指针,可以指向一个字符串,也可以指向一个对象。
无论深浅拷贝,说的都是可变变量,对于不可变变量,没有拷贝一说。浅拷贝就是把对象的第一层属性拷贝到另外一个变量中去,常用的方法是利用Object.assign或Array.slice函数来拷贝,也可以用对象省略语法 […arr] 来拷贝。深拷贝就是把对象完完整整地拷贝到另外一个变量中去,可以使用JSON.parse和JSON.stringify转换生成一个新的对象(只能拷贝enumerable的属性),另外可以利用Object.assign配合递归的方法来拷贝,这种方法就比JSON转换法复杂,但拷贝最彻底,可以把任何属性都拷贝过去。

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target); //根据source 拷贝到target
// expected output: Object { a: 1, b: 4, c: 5 }

//shadow copy sortedArr is new array to arr.
let sortedArr = [...arr].sort((a, b) => a - b);

赋值 let 和const

修饰符const定义的变量是不可以修改的,let定义的变量却可以,是不是表示用const定义的变量是不可变变量而let 定义的变量是可变变量?不是的。const 定义的是常量,在内存上是一个不可改变指针地址的变量,也就是说你可以指向一个对象(可变变量),也可以修改对象的属性,但不能赋值给另外一个对象、字符串或任何东西,也就是不能修改指针的地址。

const a = {b:2};
a.b = 3; // no error and totally ok
a = {b:2}; // throw error, no matter what value you assigned

修饰符let定义的变量可以重新赋值,但不表示这个变量是可变变量,只是变量指向的内存地址改变了,原来的值并未改变。

let a = 'this is a string';
let b = a;
a = 'this is another string'; // ok
b; // 'this is a string', no change

可变变量和不可变变量指的是字符串,数字,boolean,object,而不是let, const。

Pass-by-Value vs. Pass-by-Reference

对原始变量primitive(String, Number, boolean, null, undefine)都是进行传值/复制(两值地址分开):

let a = 3;
let b;
b = a; //copy,但是a and b 地址分开。
a = 2;
console.log("a is ", a);
console.log('b is ', b);

对可变变量(array, object, function)都是进行引用(共用一个地址)。

let age = 29;
function calculateYear(age) {
    return age + 1;
}
age = calculateYear(age);
console.log(age) //30 modify parameter
const c = { greeting: "hello" };
const d = c;
console.log("c is ", c); //hello
console.log("d is ", d); //hello
c.greeting = "Hola";
console.log("c is ", c); //Hola
console.log("d is ", d); //Hola
function changeAttribute(obj) {
    obj.greeting = "Hi";
}
changeAttribute(d);
console.log("c is ", c); //Hi
console.log("d is ", d); //Hi

Summary

  1. Immutable vs Mutable: 原始变量(生命周期不变)和object变量(改变属性)。
  2. 深浅拷贝是针对对象。
  3. 赋值let const针对其地址(指针)是否有所变化。
  4. 参数传递:传值(地址分开,copy值不影响原值)和引用(地址共用,copy值和原值互相影响)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值