js变量的类型和计算

2020-01-06  本文已影响0人  小菜鸟dreamy

js变量类型:值类型和引用类型
值类型number,string,boolean,undefined,symbol

var a = 100
var b = a
a = 200
console.log(b)

引用类型object,function

var a = {age:20}
var b = a
b.age = 21
console.log(a.age)

其中,值类型直接保存在栈内存中,值都有固定的大小,保存在栈空间,通过按值访问。引用类型保存在堆内存中的对象,值大小不固定,栈内存中存放的该对象的访问地址指向堆内存中的对象。(为什么引用类型这样存储呢?因为引用类型的值会有很多属性,值太大的话放到栈中不好管理,直接复制值的话,会导致复制过程太慢。)这种机制是基于内存空间和CPU计算的耗时来区分的。

因为存储方式不同,所以有了深拷贝浅拷贝的问题

如果是值类型,数据发生复制行为时,系统会自动给新的变量开辟一个新的空间,赋一个新的值,这些变量都相互独立,相互不影响

let a = 20;
let b = a;
b = 30;
console.log(a); // 20

如果是引用类型,数据发生复制行为时,同样会开辟一个新的空间,赋一个新的值,但这个所赋的值,是一个地址指针,这个复制的指针和被复制的指针指向同一个值

let a = { x: 10, y: 20 }
let b = a;
b.x = 5;
console.log(a.x); // 5

这种情况下,怎么办呢?如何实现深拷贝呢?
方法一:(反序列化)使用JSON.parse()和JSON.stringify()对对象进行深拷贝 (真正的进行对象的深拷贝),该方法会忽略function和undefined的字段,对date类型支持貌似也不友好。而且只能克隆原始对象自身的值,不能克隆它继承的值
方法二:es6的扩展运算符...

var a = ['a', 'b', 'c'];
var b = [...a];
b.push(2)
console.log(b) //["a", "b", "c", 2]
console.log(a) //["a", "b", "c"]

let obj = {
    name:'huahua',
    sex:'girl'
}
let obj1= {...obj}  //或者  let {...obj1}= obj
obj1.name="qq"
console.log(obj1) //{name: "huahua", sex: "girl"}
console.log(obj) //{name: "qq", sex: "girl"}

方法三:递归

function deepClone (obj={}) {
  // 判断传入的obj不为空并且是object类型
  if (obj == null || typeof obj !== "object")   return
  let res
  if (obj instanceof Array){
    res=[]
  } else {
    res={}
  }
  for (let key in obj) {
    // hasOwnProperty确保key是自身的属性而不是原型上的属性
    if (obj.hasOwnProperty(key)) {
      res[key] = deepClone (obj[key])
    }
  }
  return res
}

实现数组深拷贝:
1.slice

var a = ['a', 'b', 'c'];
var b = a.slice(0);
b.push(2)
console.log(b) //["a", "b", "c", 2]
console.log(a) //["a", "b", "c"]

2.concat

var a = ['a', 'b', 'c'];
var b = a.concat();
b.push(2)
console.log(b) //["a", "b", "c", 2]
console.log(a) //["a", "b", "c"]

所有的引用类型都可以自由的设置属性

var obj = {}
obj.a = 100

var arr = [1,2,3]
arr.a = 100   //(3) [1, 2, 3, a: 100]

function fn() {}
fn.a = 100

typeof可以判断这些类型,如下

console.log(typeof 123);  // =>number

console.log(typeof "abc");  // =>string

console.log(typeof true);  // =>boolean

console.log(typeof undefined); // =>undefined

console.log(typeof Symbol()); // =>symbol

console.log(typeof {});  // =>object

console.log(typeof []);  // =>object

console.log(typeof null);  // =>object 因为 null 也是引用类型

console.log(typeof console.log);  // =>function

值类型的判断用typeof ,引用类型的判断用instanceof

js中常见内置函数:

Object Array Boolean Number String Function Date RegExp Error

那么,JSON又是什么呢?
其实,JSON是一种数据格式。从js角度来回答的话,JSON是一个对象,有parsestringify两个方法

JSON.stringify({a:10, b:20})  //"{"a":10,"b":20}"
JSON.parse('{"a":10,"b":20}')  //{a: 10, b: 20}

变量计算
简单的变量计算,就是数字的加减乘除、字符串的拼接和替换,这个太简单了,这里不提了。但是 JS 在值类型的运算过程中,特别需要注意和利用强制类型转换这一特性,有以下场景:

var a = 100 + 10   // 110
var b = 100 + '10' // '10010'

100 == '100'   // true
0 == ''  // true
null == undefined  // true

console.log(10 && 0)  // 0
console.log('' || 'abc')  // 'abc'
console.log(!window.abc)  // true

// 判断一个变量会被当做 true 还是 false
var a = 100
console.log(!!a)
何时使用=== 何时使用==

首先,==会先试图类型转换,然后再比较,而===不会类型转换,直接比较。如下所示:

1 == '1' // true
1 === '1' // false
0 == false // true
0 === false // false
null == undefined // true
null === undefined // false

日常开发中,以下变量会被转换为false

除了以上几个,其他的都会被转换为true除了if之外,! || &&这三个运算符也会进行同样的转换,跟if是一个道理
日常开发中,都使用===,有一种情况用==,就是判断是否存在的时候

if (obj.a == null) { 
 // 这里相当于 obj.a === null || obj.a === undefined ,简写形式
}
上一篇 下一篇

猜你喜欢

热点阅读