js:变量和计算、类型

187 阅读5分钟

一、值类型

let a = 100
let b = a 
a = 200
console.log(b) // 100

屏幕快照 2022-04-02 下午1.22.36.png

二、引用类型

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

屏幕快照 2022-04-02 下午1.26.32.png

三、类型

a.基本类型 undefined, null, string, number, booleanSymbol 
b.引用类型 数组,对象,函数,RegExp类型, date

1.null,undefined,undeclared的区别

a.null表示"没有对象",即该处不应该有值,转为数值时为0。典型用法是:
  1.作为函数的参数,表示该函数的参数不是对象。
  2.作为对象原型链的终点
  3.typeof null // 'object'
  4.Number(null) // 0
b.undefined表示"缺少值",就是此处应该有一个值,但是还没有定义,转为数值时为NaN。典型用法是:
  1.变量被声明了,但没有赋值时,就等于undefined2.调用函数时,应该提供的参数没有提供,该参数等于undefined3.函数没有返回值时,默认返回undefined4.对象没有赋值的属性,该属性的值为undefined5.typeof undefined // 'undefined'
  6.Number(undefined) // NaN
c.undeclared:js语法错误,没有申明直接使用,js无法找到对应的上下文。

四、typeof运算符

a.判断所有值类型
let a; typeof a // 'undefined'
const str = 'abc'; typeof str // 'string'
const n = 100; typeof n // 'number'
const b = true; typeof b // 'boolean'
const s = Symbol('s'); typeof s // 'symbol'
b.能判断函数
typeof console.log // 'function'
typeof function () {} // 'function'
c.能识别引用类型(不能再继续识别)
typeof null // 'object'
typeof ['a', 'b'] // 'object'
typeof { x: 100 } // 'object'

五、深拷贝和浅拷贝

区别:
1.深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝

a.浅拷贝
浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,
当引用指向的值改变时也会跟着变化。

可以使用 `Object.assign`、扩展运算符 `...` 、`for in``Array.prototype.slice()``Array.prototype.concat()`
let a = {
    age: 1,
    jobs: {
        first: 'FE'
    }
}
let b = { ...a }
a.jobs.first = 'native'
console.log(b.jobs.first) // native

b.深拷贝
深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象
与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。

1.深拷贝最简单的实现是: `JSON.parse(JSON.stringify(obj))`
`JSON.parse(JSON.stringify(obj))` 是最简单的实现方式,但是有一些缺陷:
1.对象的属性值是函数时,无法拷贝。
2.原型链上的属性无法拷贝
3.不能正确的处理 Date 类型的数据
4.不能处理 RegExp
5.会忽略 symbol
6.会忽略 undefined

2.拷贝函数
const obj1 = {
    age: 20,
    name: 'xxx',
    address: {
        city: 'beijing'
    },
    arr: ['a', 'b', 'c'],
    regexp: /^1[3456789]d{9}$/,
    b: new Date()
}
function deepClone(obj) {
    if (obj instanceof RegExp) return new RegExp(obj)
    if (obj instanceof Date) return new Date(obj)
     // obj是null,或者不是对象和数组,直接返回
    if (typeof obj !== 'object' || obj == null) return obj
    // 初始化返回结果
    let result = obj instanceof Array ? [] : {}
    for (let key in obj) {
        // 保证key不是原型的属性
        if (obj.hasOwnProperty(key)) {
            // 递归调用
            result[key] = deepClone(obj[key])
        }
    }
    return result
}
console.log(deepClone(obj1))

六、类型转换

六、类型转换
 a.字符串拼接
 const a = 100 + 10 // 110
 const b = 100 + '10' // '10010'
 const c = true + '10' // 'true10'
 b.==运算符
 100 == '100' // true
 0 == '' // true
 0 == false // true
 false == '' // true
 null == undefined // true
 注意:
  除了 == null之外,其他都一律用===,例如:
  const obj = { x: 100 }
  if (obj.a == null) {} 
  相等于
  // if(obj.a === null || obj.a === undefined) {}
 c.if语句和逻辑运算
  1.truly变量: !!a === true 的变量
  2.falsely变量: !!a === false 的变量
  以下是falsely变量。除此之外都是truly变量
  !!0 === false
  !!NAN === false
  !!'' === false
  !!null === false 
  !!undefined === false 
  !!false === false
 d.逻辑判断
  console.log(10 && 0) // 0
  console.log('' || 'abc') // 'abc'
  console.log(!window.abc) // true

1.== 和 === 和 Object.is():方法判断两个值是否为同一个值 的区别

a.== 只比较值,如果类型不同,转换成相同的类型再比较,往String或者Number转
  1.== 如果两边数据类型不同,转换规则如下:
    1.布尔值===数值,则把布尔值转换为数值
    2.字符串===数值,则通过Number()把字符串转为数值
    3.如果一边是对象,则调用对象的valueof()方法后再比较
    4.null和undefined相等
    5.NaN和NaN不相等
    6.如果两边都是对象,则比较他们是不是指向同一个对象
  2.[] == ![] Type(x) 为boolean, 返回比较x == ToNumber(y)的结果
b.=== 类型和值都相等才相等
c.Object.is() 和 ===基本一样,只有下面这个区别
    console.log(+0 === -0);//true
    console.log(NaN === NaN);//false
    console.log(Object.is(+0,-0));//false
    console.log(Object.is(NaN,NaN));//true

七、JavaScript判断空数组的五种方法(前提知道是空数组)

1.将json对象转化为json字符串,再判断该字符串是否为"[]"(除外)
const arr = []
console.log(JSON.stringify(arr) === "[]") //true

2.instanceof运算符
const arr = []
arr instanceof === Array // true

3. Array.isArray(ES5的方法)
const arr = []
Array.isArray(arr) // true 

4.constructor属性指向一个对象的构造函数
const arr = []
console.log(arr.constructor === Array) // true

5.Object.prototype.toString.call
(借用Object原型的call或者apply方法,调用toString()是否为[object Array])
const arr = []
Object.prototype.toString.call(arr) === '[object Array]' // true

6. Object.prototype.isPrototypeOf
使用Object的原型方法isPrototypeOf,判断两个对象的原型是否一样, 
isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。
const arr = []
Array.prototype.isPrototypeOf(arr)  // true  

八、JavaScript判断空对象的四种方法

1.将json对象转化为json字符串,再判断该字符串是否为"{}"
const obj = {}
console.log(JSON.stringify(obj) === "{}") //true

2.constructor属性指向一个对象的构造函数(前提知道是空对象)
const obj = {} 
console.log(obj.constructor === Object) // true

3.使用for...in循环遍历对象除Symol以外的所以可枚举属性,当对象有属性存在返回false,否则返回true
function isObjectEmpty(obj) {
    if (obj.length === 0) return false
    for (let key in obj) {
        return false
    } 
    return true
}
console.log(isObjectEmpty(obj)) // true

4.使用ES6Object.keys()方法(如果是空数组也会)
const obj = {} 
const arr = Object.keys(obj) 
console.log(arr.length === 0) //true

九、判断两个数组对象和对象是不是相同

通过 JSON.stringify() 把 JavaScript 对象转换为字符串。

const obj1 = { name: 'a', age: 12}
const obj2 = { name: 'a', age: 12}
console.log(JSON.stringify(obj1) === JSON.stringify(obj2)) // true

const arr1 = [{ name: 'a', age: 12}]
const arr2 = [{ name: 'a', age: 12}]
console.log(JSON.stringify(arr1) === JSON.stringify(arr2)) // true