1, the data type
(1) six data types
There are six data types JavaScript, are Number, String, Boolean, Null, Undefined and Object
In addition to the Object is a reference type, the rest are primitive types (also called base type), which is more particularly Undefined Null and two
(2) memory model
When a method execution, will create a memory stack, this method defined variables are placed on the stack, the method call is completed, the stack immediately destroyed
Is a value stored in the stack of primitive type and reference type reference variable, the value of the reference variable to an object in the heap memory address
When an object is created, a reference variable is stored on the stack, the object itself is stored in the heap, that object is not with the end of the method call are destroyed
Actually destroying the object is determined by the garbage collection mechanism, only when the object is not referenced by any reference variables, it will be destroyed
(3) are passed by value
All function arguments are passed by value in JavaScript, but due to memory models, there will be some interesting behavior
When we modify the basic variables in a function does not modify the incoming values
When we modify the reference variable in the function, it will modify the incoming values (according to the interpretation of memory model, think about why)
let number = 123 // 基本类型
let object = { // 引用类型
name: 'Steve',
age: 18
}
function changeNumber(num) {
num = 456
}
function changeObject(obj) {
obj.age = 20
}
changeNumber(number)
changeObject(object)
console.log(number)
console.log(object.age)
/*
* 执行结果:
* 123
* 20
**/
2, the type of detection
(1)typeof
For detecting the type of a variable, it is noted that, for a variable of type array and null, typeof return object
In addition, typeof returns the object for almost all types of objects are, that can not be used typeof accurately determine an object type
let a = 0
let b = 'hello'
let c = true
let d = null
let e = undefined
let f = {}
let g = []
let h = function(){}
console.log('a: ' + typeof a)
console.log('b: ' + typeof b)
console.log('c: ' + typeof c)
console.log('d: ' + typeof d)
console.log('e: ' + typeof e)
console.log('f: ' + typeof f)
console.log('g: ' + typeof g)
console.log('h: ' + typeof h)
/*
* 执行结果:
* a: number
* b: string
* c: boolean
* d: object
* e: undefined
* f: object
* g: object
* h: function
**/
(2)Object.prototype.toString.call()
For detecting the type of a variable, you can solve the problem can not be detected typeof null and array of
let a = 0
let b = 'hello'
let c = true
let d = null
let e = undefined
let f = {}
let g = []
let h = function(){}
function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1)
}
console.log('a: ' + typeOf(a))
console.log('b: ' + typeOf(b))
console.log('c: ' + typeOf(c))
console.log('d: ' + typeOf(d))
console.log('e: ' + typeOf(e))
console.log('f: ' + typeOf(f))
console.log('g: ' + typeOf(g))
console.log('h: ' + typeOf(h))
/*
* 执行结果:
* a: Number
* b: String
* c: Boolean
* d: Null
* e: Undefined
* f: Object
* g: Array
* h: Function
**/
(3)instanceof
Used to determine if an instance belongs to a certain type, you can solve typeof can not accurately determine the object type of problem
Instanceof determines the principle is the constructor prototype property right exists in the left object prototype chain
var Message = function(descrition) { // 构造函数
this.detail = descrition
}
let message = new Message('Hello')
let object = new Object()
console.log(message instanceof Message)
console.log(message instanceof Object)
console.log(object instanceof Message)
console.log(object instanceof Object)
console.log(Message instanceof Object)
/*
* 执行结果:
* true
* true
* false
* true
* true
**/
3, type conversion
(1) cast
① String -> Number:parseInt(string[, radix])
& parseFloat(string)
parseInt
For string parsing an integer, the base can be specified; parseFloat
for resolving string to float
Both roughly the same principle, are parsed from the beginning of the first non-space character, until the end of the string or encounter an invalid numeric character
If successfully resolved, the return of figures; if the first non-space character is not a number or symbol, NaN is returned
let a = parseInt(' 123abc')
let b = parseFloat(' 123.456abc')
console.log(a)
console.log(b)
/*
* 执行结果:
* 123
* 123.456
**/
② Any -> Number:Number()
Conversion rules are as follows:
value | Conversion rules |
---|---|
Number | Direct output |
String | If the string is empty, then converted to 0 if string contains a valid integer format, converted to a decimal number if the string contains a valid floating-point format, is converted into a floating-point number if the string contains a valid ten hex format, then converted to hexadecimal number of the remaining cases, converted to NaN |
Boolean | If true, it is converted into 1 if it is false, 0 is converted into |
Null | Converted into 0 |
Undefined | Converted into 0 |
Object | Object of the calling valueOf() method, according to the above rule conversion if it is NaN, the Object calling toString() method, according to the above rule conversion |
let a = Number(123)
let b = Number('456')
let c = Number(true)
let d = Number(false)
let e = Number(null)
let f = Number(undefined)
let g = Number(new Date())
let h = Number(new Array())
console.log(a)
console.log(b)
console.log(c)
console.log(d)
console.log(e)
console.log(f)
console.log(g)
console.log(h)
/*
* 执行结果:
* 123
* 456
* 1
* 0
* 0
* NaN
* 1578556849729
* 0
**/
③ Any -> String:String()
Conversion rules are as follows:
value | Conversion rules |
---|---|
Number | Converted into a digital value |
String | Direct output |
Boolean | If true, converted to true if it is false, false converted into |
Null | Convert null |
Undefined | Convert undefined |
Object | Conversion according to specific rules |
let a = String(123)
let b = String('asdf')
let c = String(true)
let d = String(false)
let e = String(null)
let f = String(undefined)
let g = String({})
let h = String([123, 'asdf', true, false, null, undefined])
console.log(a)
console.log(b)
console.log(c)
console.log(d)
console.log(e)
console.log(f)
console.log(g)
console.log(h)
/*
* 执行结果:
* 123
* asdf
* true
* false
* null
* undefined
* [object Object]
* 123,asdf,true,false,,
**/
(2) automatic conversion
Analyzing conditions ①
During determination condition, the value of the variable will be automatically converted to a Boolean value in accordance with the rules, the rules of conversion as follows:
value | Conversion rules |
---|---|
Number | 0, NaN false converted into other cases converted to true |
String | False empty string converted into the remaining cases converted to true |
Null | Converted into false |
Undefined | Converted into false |
Object | Converted to true |
let a = 123
let b = ''
let c = null
let d = undefined
let e = {}
a ? console.log('true') : console.log('false')
b ? console.log('true') : console.log('false')
c ? console.log('true') : console.log('false')
d ? console.log('true') : console.log('false')
e ? console.log('true') : console.log('false')
/*
* 执行结果:
* true
* false
* false
* false
* true
**/
② numerical operations
For the
+
operator, the conversion rule is as follows:If the operand is not a string or object, by
Number()
converting into Number Type FunctionIf there is an object or string operands, through
String()
converted into String type of the function
let a = 1 + true
let b = 1 + null
let c = 1 + undefined
let d = '1' + true
let e = '1' + null
let f = '1' + undefined
let g = '1' + 1
let h = {} + true
let i = [] + false
console.log(a)
console.log(b)
console.log(c)
console.log(d)
console.log(e)
console.log(f)
console.log(g)
console.log(h)
console.log(i)
/*
* 执行结果:
* 2
* 1
* NaN
* 1true
* 1null
* 1undefined
* 11
* [object Object]true
* false
**/
- For
-
,*
,/
,%
operator, through both the firstNumber()
function into numerical calculation then
Implicit conversion rule based on numerical computation, we can easily obtain a shortcut number string interconversion
// number -> string
let number = 123
let string = number + ''
console.log(typeof string)
console.log(string)
/*
* 执行结果:
* string
* 123
**/
// string -> number
let string = '123'
let number = string - 0
console.log(typeof number)
console.log(number)
/*
* 执行结果:
* number
* 123
**/
③ equality operators
In use ==
when the operator to compare the two variables are equal, if different types of variables, will then first comparison implicit conversion rules are as follows:
order | Variable 1 | Variable 2 | operating |
---|---|---|---|
1 | NaN | * | Return false |
2 | Null | Undefined | Returns true |
3 | Null | Null | Returns true |
4 | Undefined | Undefined | Returns true |
5 | Null | In addition to Null, Undefined outside | Return false |
6 | Undefined | In addition to Null, Undefined outside | Return false |
7 | Boolean | * | After converted into Boolean Comparison Number |
8 | Object | Object | When two objects point to the same memory address, will be equal |
9 | Object | Number、String | After Object converted into the original value (Number / String) comparing the first to use valueOf() a method if the object can be converted to the original value, the result is returned otherwise the toString() method if the object can be converted to the original value, then the results are returned or thrown TypeError exception |
10 | Number | Number | Direct comparison |
11 | String | String | Direct comparison |
12 | String | Number | When you convert a String to compare Number |
Practice a few topics:
false == 0 // true
false == '0' // true
false == [] // true
false == {} // false
123 == [123] // true
2 == { valueOf(){ return 2 }} // true
1 == { valueOf: function(){ return [] }, toString: function(){ return 1 }} // true
The use ==
time will be determined implicit conversion, it is generally used in the project===
4, assignment, shallow vs. deep copy
For basic types, assignment, deep and shallow copy copy all the old values of variables copied to a new variable, independently of each other between the old and new variable
let number = 159
let string = 'hello'
let number_copy = number
let string_copy = string
number_copy = 258
string_copy = 'hi'
console.log('number: ' + number) // 原变量的值不会改变
console.log('string: ' + string) // 原变量的值不会改变
console.log('number_copy: ' + number_copy)
console.log('string_copy: ' + string_copy)
/*
* 执行结果:
* number: 159
* string: hello
* number_copy: 258
* string_copy: hi
**/
For reference types:
- 赋值后新旧变量指向同一个内存地址,此时改变新变量会影响旧变量的值
let object = { first_name: 'Steve', last_name: 'Jobs' }
let array = [1, 3, 5]
let object_copy = object
let array_copy = array
object_copy['first_name'] = 'Steven'
array_copy[0] = 2
console.log('object["first_name"]: ' + object['first_name']) // 原变量的值发生改变
console.log('array[0]: ' + array[0]) // 原变量的值发生改变
console.log('object_copy["first_name"]: ' + object_copy['first_name'])
console.log('array_copy[0]: ' + array_copy[0])
/*
* 执行结果:
* object["first_name"]: Steven
* array[0]: 2
* object_copy["first_name"]: Steven
* array_copy[0]: 2
**/
- 浅拷贝得到的新变量,是将旧变量的第一层数据 赋值 给新变量
// 对于对象,常用的浅拷贝方式有:Object.assign
// 对于数组,常用的浅拷贝方式有:Array.from、slice、concat
let object = {
name: {
first_name: 'Steve',
last_name: 'Jobs'
},
age: 18
}
let array = [[1, 3], 5, 7]
let object_shallow_copy = Object.assign({}, object)
let array_shallow_copy = Array.from(array)
object_shallow_copy['name']['first_name'] = 'Steven'
object_shallow_copy['age'] = 20
array_shallow_copy[0][0] = 2
array_shallow_copy[2] = 11
console.log('object["name"]["first_name"]: ' + object['name']['first_name'])
console.log('object["age"]: ' + object['age'])
console.log('array[0][0]: ' + array[0][0])
console.log('array[2]: ' + array[2])
console.log('object_shallow_copy["name"]["first_name"]: ' + object_shallow_copy['name']['first_name'])
console.log('object_shallow_copy["age"]: ' + object_shallow_copy['age'])
console.log('array_shallow_copy[0][0]: ' + array_shallow_copy[0][0])
console.log('array_shallow_copy[2]: ' + array_shallow_copy[2])
/*
* 执行结果:
* object["name"]["first_name"]: Steven
* object["age"]: 18
* array[0][0]: 2
* array[2]: 7
* object_shallow_copy["name"]["first_name"]: Steven
* object_shallow_copy["age"]: 20
* array_shallow_copy[0][0]: 2
* array_shallow_copy[2]: 11
**/
自己来实现一个浅拷贝函数:
function shallowCopy(object) {
if (typeof object !== 'object') return
let newObject = object instanceof Array ? [] : {}
for (let key in object) {
if (object.hasOwnProperty(key)) {
newObject[key] = object[key]
}
}
return newObject
}
- 深拷贝得到的新变量,是将旧变量的所有数据(无论嵌套多深)都 复制 给新变量,新旧变量之间互不影响
// 最简单的方法就是 JSON.parse(JSON.stringify())
let object = {
name: {
first_name: 'Steve',
last_name: 'Jobs'
},
age: 18
}
let array = [[1, 3], 5, 7]
let object_deep_copy = JSON.parse(JSON.stringify(object))
let array_deep_copy = JSON.parse(JSON.stringify(array))
object_deep_copy['name']['first_name'] = 'Steven'
object_deep_copy['age'] = 20
array_deep_copy[0][0] = 2
array_deep_copy[2] = 11
console.log('object["name"]["first_name"]: ' + object['name']['first_name'])
console.log('object["age"]: ' + object['age'])
console.log('array[0][0]: ' + array[0][0])
console.log('array[2]: ' + array[2])
console.log('object_deep_copy["name"]["first_name"]: ' + object_deep_copy['name']['first_name'])
console.log('object_deep_copy["age"]: ' + object_deep_copy['age'])
console.log('array_deep_copy[0][0]: ' + array_deep_copy[0][0])
console.log('array_deep_copy[2]: ' + array_deep_copy[2])
/*
* 执行结果:
* object["name"]["first_name"]: Steve
* object["age"]: 18
* array[0][0]: 1
* array[2]: 7
* object_deep_copy["name"]["first_name"]: Steven
* object_deep_copy["age"]: 20
* array_deep_copy[0][0]: 2
* array_deep_copy[2]: 11
**/
自己来实现一个深拷贝函数:
function deepCopy(object) {
if (typeof object !== 'object') return
let newObject = object instanceof Array ? [] : {}
for (let key in object) {
if (object.hasOwnProperty(key)) {
let item = object[key]
newObject[key] = typeof item === 'object' ? deepCopy(item) : item
}
}
return newObject
}
【 阅读更多 JavaScript 系列文章,请看 JavaScript学习笔记 】