[TOC]
# 基本概念
7 種數據類型: `Null、Undefined、Number、Boolean、String、Object、Symbol`
排除 Symbol 的話,《JavaScript 高級程序設計》中將 Undefined、Null、Number、Boolean、String 定義為基本數據類型,因為其是按值訪問的,可以操作保存在變量中的實際的值。引用類型值是保存在內存中的對象,操作對象時,實際上操作的是對象的引用。
[鏈接:js 中的值類型和引用類型的區別](https://www.cnblogs.com/leiting/p/8081413.html)
如何判斷變量的數據類型?
使用`typeof`運算符:
* typeof 對于基本類型,除了 null 都可以顯示正確的類型
* typeof 對于對象,除了函數都會顯示 object
* 對于 null 來說,雖然它是基本類型,但是會顯示 object,這是一個存在很久了的 Bug
```javaScript
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof b // b沒有聲明,但是還會顯示undefined
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
typeof null // 'object'
```
使用`Object.prototype.toString.call()`,該方法返回類似`[object Type]`形式的字符串
```javaScript
let a = []
let b = {}
let c = true
let d = 'string'
let e = null
let f = undefined
let g = 1
let h = function () {}
let i = Symbol('symbol')
console.log(Object.prototype.toString.call(a)) // [object Array]
console.log(Object.prototype.toString.call(b)) // [object Object]
console.log(Object.prototype.toString.call(c)) // [object Boolean]
console.log(Object.prototype.toString.call(d)) // [object String]
console.log(Object.prototype.toString.call(e)) // [object Null]
console.log(Object.prototype.toString.call(f)) // [object Undefined]
console.log(Object.prototype.toString.call(g)) // [object Number]
console.log(Object.prototype.toString.call(h)) // [object Function]
console.log(Object.prototype.toString.call(i)) // [object Symbol]
console.log('[object Array]' === Object.prototype.toString.call(a)) // true
```
## if 條件判斷時的注意事項
| 數據類型 | 轉換為 true 的值 | 轉換為 false 的值 |
| --- | --- | --- |
| Boolean | true | false |
| String | 任何非空字符串 | "" (空字符串) |
| Number| 任何非零數字值(包括無窮大) | 0 和 NaN |
| Object| 任何對象 | null |
| Undefined| N/A(不適用) | undefined |
## 邏輯非
- 如果操作數是一個對象,返回 false
- 如果操作數是一個空字符串,返回 true
- 如果操作數是一個非空字符串,返回 false
- 如果操作數是數值 0,返回 true
- 如果操作數是任意非 0 的值(包括 Infinity),返回 false
- 如果操作數是 null,返回 true
- 如果操作數是 NaN,返回 true
- 如果操作數是 undefined,返回 true
## 四則運算注意事項
只有當**加法運算**時,其中一方是字符串類型,就會把另一個也轉為字符串類型。其他運算只要其中一方是數字,那么另一方就轉為數字。并且加法運算會觸發三種類型轉換:將值轉換為原始值,轉換為數字,轉換為字符串。
``` js
1 + '1' // '11'
2 * '2' // 4
[1, 2] + [2, 1] // '1,22,1'
// [1, 2].toString() -> '1,2'
// [2, 1].toString() -> '2,1'
// '1,2' + '2,1' = '1,22,1'
```
對于加號需要注意這個表達式`'a' + + 'b'`
```js
'a' + + 'b' // -> "aNaN"
// 因為 + 'b' -> NaN
// 你也許在一些代碼中看到過 + '1' -> 1
```
## toString() 方法的使用
數值、布爾值、對象和字符串值(沒錯,每個字符串也都有一個 toString() 方法,該方法返回字符串的一個副本)都有 toString() 方法。但 null 和 undefined 值沒有這個方法。
多數情況下,調用 toString() 方法不必傳遞參數。但是,在調用數值的 toString() 方法時,可以傳遞一個參數:輸出數值的基數。默認情況下,toString() 方法以十進制格式返回數值的字符串表示。而通過傳遞基數,toString() 可以輸出以二進制、八進制、十六進制,乃至其他任意有效進制格式表示的字符串值。下面給出幾個例子:
```js
var num = 10
alert(num.toString()) // "10"
alert(num.toString(2)) // "1010"
alert(num.toString(8)) // "12"
alert(num.toString(10)) // "10"
alert(num.toString(16)) // "a"
```
# 變量、函數提升
在生成執行上下文時,會有兩個階段。第一個階段是創建的階段,JS 解釋器會找出需要提升的變量和函數,并且給他們提前在內存中開辟好空間,函數的話會將整個函數存入內存中,變量只聲明并且賦值為 undefined。在第二個階段,也就是代碼執行階段,我們可以直接提前使用。**在提升的過程中,相同的函數會覆蓋上一個函數,并且函數優先于變量提升**
簡而言之:由于變量提升,使用 var 聲明的變量聲明前使用則值為 undefined(本作用域下),函數可以在聲明之前就使用。
``` javaScript
b() // call b
console.log(a) // undefined
var a = 'Hello world'
function b() {
console.log('call b')
}
var b = 'I am a var'
```
如果你想深入了解這一過程,可以 [點擊這里](http://www.hmoore.net/book/chenmk/web-knowledges/edit)
# instanceof
instanceof 運算符用于測試構造函數的 prototype 屬性是否出現在對象的原型鏈中的任何位置
用法:`對象 instanceof 構造函數`
```javaScript
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var auto = new Car('Honda', 'Accord', 1998);
console.log(auto instanceof Car);
// expected output: true
console.log(auto instanceof Object);
// expected output: true
```
# Object 對象
參考:[https://www.jb51.net/article/80177.htm](https://www.jb51.net/article/80177.htm)
**對象實例的一些方法**
- hasOwnProperty(propertyName):接收一個字符串參數,該參數表示屬性名稱,用來判斷該屬性是否在當前對象實例中,而不是在對象的原型鏈中。
```
var arr = []
console.log(arr.hasOwnProperty("length")) // true
console.log(arr.hasOwnProperty("hasOwnProperty")) // false
// length 是 arr 自己的屬性,而 hasOwnProperty 是原型鏈上的屬性(方法)
```
- isPrototypeOf(Object):isPrototype 方法接收一個對象,用來判斷當前對象是否在傳入的參數對象的原型鏈上。關于原型鏈可參考原型與繼承章節。
```
function MyObject() {}
var obj = new MyObject()
console.log(Object.prototype.isPrototypeOf(obj)) // true
```
- toString():返對象的字符串表示
- valueOf():返回對象的原始值,可能是字符串、數值、bool 值等,看具體的對象
**特性操作的相關方法:**
- Object.defineProperty(obj, propName, descriptor):接收三個參數,obj 是需要定義屬性的對象,propName 是需要被定義 / 修改的屬性名,descriptor 是屬性描述符,包含一些屬性的特性定義
```
var obj = {}
Object.defineProperty(obj, "name", {
value: "name", // 該屬性的數據值,默認為 undefined
configurable: true, // 表示能否通過 delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性,默認為 true
writable: true, // 表示能否修改屬性的值,默認為 true
enumerable: true, // 表示能否通過 for-in 循環返回屬性,默認為 true
get: function () {}, // 訪問器屬性,在讀取屬性時調用的函數,默認為 undefined
set: function () {} // 訪問器屬性,在寫入屬性時調用的函數,默認為 undefined
})
```
- Object.defineProperties():與 defineProperty 不同之處在于可以同時定義多個屬性
```
var obj = {};
Object.defineProperty(obj, {
"name": {
value: "name",
configurable: true,
writable: true,
enumerable: true
},
"age": {
value: 20
}
})
```
- Object.getOwnPropertyDescriptor(obj, propName):用于讀取特性值,接收對象及其屬性名兩個參數,返回一個對象
```
var person = {
_age: 10,
type: "小孩"
}
Object.defineProperty(person, "age", {
get: function () {
return this._age
},
set: function (newValue) {
this._age = newValue
this.type = newValue > 17 ? "成人" : "小孩"
}
})
console.log(Object.getOwnPropertyDescriptor(person, "type"))
// Object {value: "成人", writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(person, "age"))
// Object {enumerable: false, configurable: false, get: function(),set: function ()}
```
**其他:**
- Object.getOwnPropertyNames():用于獲取對象自身的所有屬性,包括可枚舉和不可枚舉的所有屬性,返回一個數組
```
function Parent() {
this.lastName = "Black"
}
function Child(firstName) {
this.firstName = firstName
}
Child.prototype = new Parent()
var son = new Child("Jack");
Object.defineProperty(son, "age", {
enumerable: false
})
console.log(Object.keys(son)) // ["firstName"]
console.log(Object.getOwnPropertyNames(son)) // ["firstName", "age"]
```
- Object.keys():用于獲取給定對象的所有可枚舉的自身屬性的屬性名,它返回一個數組,例子如上
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直線、矩形、多邊形
- Part2-曲線圖形
- Part3-線條操作
- Part4-文本操作
- Part5-圖像操作
- Part6-變形操作
- Part7-像素操作
- Part8-漸變與陰影
- Part9-路徑與狀態
- Part10-物理動畫
- Part11-邊界檢測
- Part12-碰撞檢測
- Part13-用戶交互
- Part14-高級動畫
- CSS
- SCSS
- codePen
- 速查表
- 面試題
- 《CSS Secrets》
- SVG
- 移動端適配
- 濾鏡(filter)的使用
- JS
- 基礎概念
- 作用域、作用域鏈、閉包
- this
- 原型與繼承
- 數組、字符串、Map、Set方法整理
- 垃圾回收機制
- DOM
- BOM
- 事件循環
- 嚴格模式
- 正則表達式
- ES6部分
- 設計模式
- AJAX
- 模塊化
- 讀冴羽博客筆記
- 第一部分總結-深入JS系列
- 第二部分總結-專題系列
- 第三部分總結-ES6系列
- 網絡請求中的數據類型
- 事件
- 表單
- 函數式編程
- Tips
- JS-Coding
- Framework
- Vue
- 書寫規范
- 基礎
- vue-router & vuex
- 深入淺出 Vue
- 響應式原理及其他
- new Vue 發生了什么
- 組件化
- 編譯流程
- Vue Router
- Vuex
- 前端路由的簡單實現
- React
- 基礎
- 書寫規范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 與 Hook
- 《深入淺出React和Redux》筆記
- 前半部分
- 后半部分
- react-transition-group
- Vue 與 React 的對比
- 工程化與架構
- Hybird
- React Native
- 新手上路
- 內置組件
- 常用插件
- 問題記錄
- Echarts
- 基礎
- Electron
- 序言
- 配置 Electron 開發環境 & 基礎概念
- React + TypeScript 仿 Antd
- TypeScript 基礎
- React + ts
- 樣式設計
- 組件測試
- 圖標解決方案
- Storybook 的使用
- Input 組件
- 在線 mock server
- 打包與發布
- Algorithm
- 排序算法及常見問題
- 劍指 offer
- 動態規劃
- DataStruct
- 概述
- 樹
- 鏈表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 課程實戰記錄
- 服務器
- 操作系統基礎知識
- Linux
- Nginx
- redis
- node.js
- 基礎及原生模塊
- express框架
- node.js操作數據庫
- 《深入淺出 node.js》筆記
- 前半部分
- 后半部分
- 數據庫
- SQL
- 面試題收集
- 智力題
- 面試題精選1
- 面試題精選2
- 問答篇
- 2025面試題收集
- Other
- markdown 書寫
- Git
- LaTex 常用命令
- Bugs