首先,我们要清楚JS是一门弱类型且是动态类型的语言。
弱类型就是可以让你进行一些隐式转换,如[] == 0为true,而强类型的就不行;
动态类型就是在代码运行时才去检测类型,比如a = 3; a.push(3);结果是运行时报错,而静态类型是在编译时就会报错。
想深入了解的同学可以去:弱类型、强类型、动态类型、静态类型语言的区别是什么?
JS中总共有三种声明变量的方式: var , let , const
var: 不支持块级作用域,存在变量提升
console.log(a) // undefined 变量赋值会提升,但会先为undefined,执行时才赋值
b() // true 函数声明会提升
var a = 3
function b() {
console.log(true)
}
let: 支持块级作用域,暂存死区,不存在变量提升
const log = console.log.bind(console)
// 不存在变量提升
log(a) // ReferenceError: a is not defined
let a = 3
if (true) {
let b = 2
// let b 暂存死区
let b = 3 // SyntaxError: Identifier 'b' has already been declared
}
// let让if{}生成块状作用域,外面并不能引用
log(b) // ReferenceError: b is not defined
了解let更多作用:let-MDN
const: 定义一个常量,这个常量的值不能被改变
const log = console.log.bind(console)
const TYPE = 1
TYPE = 2 // TypeError: Assignment to constant variable.
const DB_CONF = {name: 'Mysql'}
DB_CONF.name = 'Mongodb'
log(DB_CONF) // {name: 'Mongodb'},原因是DB_CONF指向的地址没发生变化,只是对象的内容发生变化了
JavaScript中的数据类型有:undefined, null, Boolean, Number, String, Object, Symbol
基本类型: undefined, null, Boolean, Number, String,Symbol
引用类型: Object(Array, Function, Date, RegExp)
基本类型传递的是值,而引用类型传递的是引用,我们能不能把基本类型转换为引用类型呢?
// 只拿Number举例,String也是一样的
var t = 3
var t1 = new Number(t)
log(typeof t) // number
log(typeof t1) // object
log(t1.valueOf()) // 3
既然基本类型可以转换为引用类型,那为什么还需要基本类型呢?
引用类型Object是需要new构造的,是会存放在内存的堆中,如果把简简单单的var t = 3 放在堆中无疑太浪费存储了,所以直接把基本类型的值存放在堆栈中,这样既节省了内存,又不用管理它的回收,因为是计算机自动回收。
谈谈JavaScript中的对象Object
计算属性
let key = 'name'
var DB = {
[key]: 'Mysql'
}
log(DB['name']) // Mysql
new只是一个语法糖而已
const log = console.log.bind(console)
function kclass(construct, proto) {
return function fn(...args) {
// 构造原型
let obj = Object.create(proto)
fn.prototype = proto
obj.constructor = construct
// 调用构造方法
obj.constructor(...args)
// 返回对象
return obj
}
}
let Animal = kclass(function (name, age) {
this.name = name
this.age = age
}, {
getName () {
return this.name
},
getAge () {
return this.age
}
})
let Dog = Animal('Dog', 3)
log(Dog.getName(), Dog.getAge()) // Dog 3
对象的浅拷贝与深拷贝
let Dog = {
name: 'Dog',
home: {
province: 'a1',
address: 'a2'
}
}
let Cat = {
name: 'Cat',
home: {
province: 'c1',
address: 'c2'
}
}
// 浅拷贝
Object.assign(Dog, Cat)
Cat.name = 'cat1'
Cat.home.address = 'c3'
log(Dog) // Dog.home.address = 'c3' Dog里的引用对象的值也随Cat变了
--------------------------------------------------------------------------------------
// 对象深拷贝
const deepCopy = function (source, target) {
Object.keys(target).forEach(k => {
if (target[k] instanceof Object) {
source[k] = source[k] || {}
deepCopy(source[k], target[k])
} else {
source[k] = target[k]
}
})
return source
}
const merge = function (source, ...target) {
target.forEach(t => {
deepCopy(source, t)
})
return source
// return [source, ...target].reduce((a, b) => deepCopy(a, b)) // 第二种写法
}
merge(Dog, Cat)
Cat.name = 'cat2'
Cat.home.address = 'c4'
log(Dog) // Dog.home.address 还是 c2