# 變量類型
## 6種原始類型\(值類型\):
1. boolean
2. string
3. number
4. **null**
5. undefined
6. symbol \(es6\)
**注意**
原始類型存儲的都是值,是不能調用方法的,像 "1".valueOf() 能調用是因為:這里的 "1" 會被自動裝箱為 String (包裝類)。
null 不是 Object,是原始類型,typeof null 會輸出 object 是因為js的bug
undefined: 沒有賦值變量的默認值,自動賦值
null:表示一個變量不再指向任何對象地址
## 引用類型
在 JS 中,除了原始類型那么其他的都是對象類型了。對象類型和原始類型不同的是,原始類型存儲的是值,對象類型存儲的是地址(指針)。當你創建了一個對象類型的時候,計算機會在內存中幫我們開辟一個空間來存放值,但是我們需要找到這個空間,這個空間會擁有一個地址(指針)
```
function test(person) {
person.age = 26
person = {
name: 'yyy',
age: 30
}
return person
}
const p1 = {
name: 'yck',
age: 25
}
const p2 = test(p1)
console.log(p1) // -> ?
console.log(p2) // -> ?
```
* test\(p1\) 將p1的對象地址當作函數參數
* person.age = 26 會將對象p1的age也修改
* person = {name: 'yyy',age: 30} person對象的地址重新指向新對象,和p1不在綁定
* const p2 = test\(p1\) 將方法里person的地址傳遞給p2
按值傳遞的類型,復制一份存入棧內存,這類類型一般不占用太多內存,而且按值傳遞保證了其訪問速度。按共享傳遞的類型,是復制其引用,而不是整個復制其值(C 語言中的指針),保證過大的對象等不會因為不停復制內容而造成內存的浪費
## typeof
能檢測出七種類型,值類型中null的結果是object,引用類型中出來函數顯示為Function,其他都是object,所以能檢測出七種(5個值類型對應的+1個object+1個Function。typeof 并不能準確判斷對象變量到底是什么類型
| type | 結果 |
| :--- | :--- |
| typeof 123 | number |
| typeof '123' | string |
| typeof true | boolean |
| typeof undefined | undefined |
| typeof Symbol\(\) | symbol |
| typeof function | Function |
| typeof null | object |
| typeof \[1,2\] | object |
| typeof {} | object |
## instanceof
instanceof運算符用于測試構造函數的prototype屬性是否出現在對象的原型鏈中的任何位置
```
[1, 2] instanceof Array
const Person = function() {}
const p1 = new Person()
p1 instanceof Person
```
instanceof更多是用來檢測自定義對象
## 判斷對象變量到底是什么類型的方法
```
function is(type, obj) {
var clas = Object.prototype.toString.call(obj).slice(8, -1);
return obj !== undefined && obj !== null && clas === type;
}
is('String', 'test'); // true
is('String', new String('test')); // true
Object.prototype.toString 返回一種標準格式字符串,所以上例可以通過 slice 截取指定位置的字符串,如下所示:
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(2) // "[object Number]"
```
# 類型轉換

# this
## this的綁定規則:
1. 在非嚴格模式下,默認綁定的this指向全局對象,嚴格模式下this指向undefined
2. 函數調用 foo\(\) 這里的this也會指向全局對象
3. test.foo\(\) this指向test對象, 指向調用者
4. new foo\(\) 在函數內部,this 指向新創建的對象。
5. 當使用 Function.prototype 上的 call 或者 apply 方法時,函數內的 this 將會被 顯式設置為函數調用的第一個參數。
```
function a() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(a()()())
```
首先箭頭函數其實是沒有 this 的,箭頭函數中的 this 只取決包裹箭頭函數的第一個普通函數的 this。在這個例子中,因為包裹箭頭函數的第一個普通函數是 a,所以此時的 this 是 window。另外對箭頭函數使用 bind 這類函數是無效的。
```
let a = {}
let fn = function () { console.log(this) }
fn.bind().bind(a)() // => ?
```
可以從上述代碼中發現,不管我們給函數 bind 幾次,fn 中的 this 永遠由第一次 bind 決定,所以結果永遠是 window。
```
var foo=function(m,n){
console.log(n);
return {
foo:function(o){
console.log(o);
return foo(o,m);
}
}
}
//問題一:
var result=foo(1);
result.foo(2);
result.foo(3);
result.foo(4);
//問題二:
var result=foo(2).foo(3).foo(4).foo(5);
//問題三:
var result=foo(1);
result.foo(2).foo(3);
result.foo(4).foo(5);
//問題一二三分別輸出什么? 說出執行步驟
```
# == 和 ===
== 如果對比雙方的類型不一樣的話,就會進行類型轉換

```
[] == ![] //
```
=== 就是判斷兩者類型和值是否相同
true, ! 的優先級比 == 大,所以 !\[\] 轉為1 即 \[\] == 1 ,對象和number判斷會將對象轉為基本類型,即 1==1 結果為true
# let var const
let 、const與var的區別
1. 變量不會提示,塊級作用域,使用前需要先定義,如果在聲明之前訪問這些變量,會導致報錯
2. 重復聲明報錯
3. 不綁定全局作用域,全局作用域中,let 聲明的變量不會掛在window上,var聲明的會
let和const的區別
const 用于聲明常量,其值一旦被設定不能再被修改,否則會報錯
# 閉包
## 什么是閉包
《JavaScript高級程序設計》這樣描述:
```
閉包是指有權訪問另一個函數作用域中的變量的函數;
```
《JavaScript權威指南》這樣描述:
```
從技術的角度講,所有的JavaScript函數都是閉包:它們都是對象,它們都關聯到作用域鏈。
```
《你不知道的JavaScript》這樣描述:
```
當函數可以記住并訪問所在的詞法作用域時,就產生了閉包,即使函數是在當前詞法作用域之外執行。
```
```
function fn1() {
var name = 'iceman';
function fn2() {
console.log(name);
}
return fn2;
}
var fn3 = fn1();
fn3();
```
這樣就清晰地展示了閉包:
自由變量將從作用域鏈中去尋找,但是 依據的是**函數定義時的作用域鏈,而不是函數執行時**,
1. fn2的詞法作用域能訪問fn1的作用域
2. 將fn2當做一個值返回
3. fn1執行后,將fn2的引用賦值給fn3
4. 執行fn3,輸出了變量name
## 循環中使用閉包解決 `var` 定義函數的問題
for \(var i = 1; i <= 5; i++\) {
\(function\(j\) {
setTimeout\(function timer\(\) {
console.log\(j\)
}, j \* 1000\)
}\)\(i\)
}
## 閉包優缺點
優點:
1. 因為在閉包內部保持了對外部活動對象的訪問,但外部的變量卻無法直接訪問內部,避免了全局污染;
2. 可以當做私有成員,彌補了因js語法帶來的面向對象編程的不足;
3. 可以長久的在內存中保存一個自己想要保存的變量.
缺點:
1. 可能導致內存占用過多,因為閉包攜帶了自身的函數作用域
2. 閉包只能取得外部包含函數中得最后一個值
# 深淺拷貝
## 淺拷貝
對象類型在賦值的過程中其實是復制了地址,從而會導致改變了對象里的數據,其他也都會被改變,且不會拷貝對象的內部的子對象。
## 深拷貝
JSON.parse\(JSON.stringify\(object\)\)
1. 會忽略 undefined
2. 會忽略 symbol
3. 不能序列化函數
4. 不能解決循環引用的對象
# 原型
* 所有的引用類型(數組、對象、函數),都具有對象特性,即可自由擴展屬性(null除外)
* 所有的引用類型(數組、對象、函數),都有一個**proto**屬性,屬性值是一個普通的對象
* 所有的函數,都有一個prototype屬性,屬性值也是一個普通的對象
* 所有的引用類型(數組、對象、函數),**proto**屬性值指向它的構造函數的prototype屬性值
創建原型的三種方式:
第一種:字面量
```
var o1 = {name: '01}
var o2 = new Object({name: 'o2'});
```
第二種:構造函數
```
function Person(name) {this.name = name;}
var o3 = new M('o3');
```
第三種:Object.create
```
var p = {name: 'p'};
var o4 = Object.create(p);
```
# 原型鏈
當試圖得到一個對象的某個屬性時,如果這個對象本身沒有這個屬性,那么會去它的**proto**(即它的構造函數的prototype)中尋找,沒有找到,還會繼續往上找。這樣一直往上找,你會發現是一個鏈式的結構,所以叫做“原型鏈”。如果一直找到最上層都沒有找到,那么就宣告失敗,返回undefined。最上層是什么 —— Object.prototype.**proto** === null


# new 運算符
new 運算符實現原理

# 繼承
## 構造函數繼承
原理: 將父級的構造函數this指向到子類構造函數this上面
```
function Person() {
this.name = "person";
}
function Child() {
Person.call(this);
this.age = 22;
}
```
缺點: 父級的原型鏈上的變量和方法無法繼承過來
## 原型鏈繼承
原理: 子類的原型(prototype)等于父類實例
```
function Person() {
this.name = "person";
}
function Child() {
this.age = 22;
}
Child.prototype = Person.prototype;
```
缺點: 原型中所有屬性是被很多實例共享的,共享對于函數非常合適,對于包含基本值的屬性 也還可以。但如果屬性包含引用類型就會導致改變一個就是改變所有。
## 組合繼承
原理: 不共享的使用構造函數,共享的使用原型鏈,子類的原型等于Object.create\(父類原型\),同時覆蓋子類原型的construct 。(使用new Person \(\) 會造成父類構造函數執行兩遍。不能將父類的原型鏈(prototype)直接賦值給子類,會造成實例無法區分是使用子類還是父類創建的,因為是同一個prototype。Object.create\(\) 會創建一個中間對象,將父類和子類隔離)
```
function Person() {
this.name = "person";
}
function Child() {
Person.call(this);
this.age = 22;
}
Child.prototype = Object.create(Person.prototype);
Child.prototype.construct = Child;
```
- 筆記內容來源
- 你不知道的JavaScript上
- vue
- 環境搭建
- node和npm安裝配置
- 安裝vue-cli并初始化vue項目
- 安裝配置elementUI
- vuex安裝配置
- axios安裝配置
- main.js
- vue基礎入門
- vue-router介紹
- vuex
- vue 原理學習源碼學習
- js正則處理v-bind和語法
- 雙向綁定
- 虛擬dom
- mvvm和render函數
- vue工作項目筆記
- elementUI 表格分頁多選記憶功能
- elementUI表格展開一行
- keepAlive
- vue整合ckeditor5
- this.$router.push 內打開新窗口
- java修改上傳圖片的權限
- 兼容ie11
- 生成二維碼
- base64圖片下載(兼容IE10)
- vue新手引導程序intro.js
- vue插件 devtools
- vue刷新當前頁面
- vue 錨點導航
- axios
- axios與springmvc
- vue-cli 3搭建vue
- git
- git常用命令
- 正則表達式
- 實例demo
- 1
- 新手引導頁
- 純css3從左顯示下劃線動畫導航菜單
- 純css3從中間顯示下劃線動畫導航菜單
- css顯示密碼
- 倒計時時鐘
- 星星評分
- 按鈕懸停效果
- 步驟條
- css動畫按鈕
- input標題獲得焦點上移
- css圖片放大
- css鏡像導航欄
- js
- 通信
- for in 和 for of
- 前端安全問題
- Promise
- 掘金冴羽學習筆記
- 模擬call
- 模擬bind
- 閉包
- 1 作用域
- 2 執行上下文棧
- 3 變量對象
- 4 作用域鏈
- 5 this
- 面向對象
- 基礎知識點
- 渲染機制
- 其他
- 判斷是否為數組
- http
- css
- 基礎知識
- css陰影