owned this note
owned this note
Published
Linked with GitHub
# JS 必備觀念
## 常見縮寫
### 語法糖
不會影響運作,邏輯與當前 JS 一致
```javascript=
const obj = {
myName: '物件',
fn: function() {
return this.myName;
}
// 省略冒號和function:
fn() {
return this.myName;
}
}
console.log(obj.fn()); // 結果不變
```
### 物件字面值 Object literals
```javascript=
const person = {
name: '小明'
};
const people = {
// person: person
// 當屬性與值同名時,可省略屬性
person
}
console.log(people)
// 結果都是 person = {name: '小明'}
```
### 展開
```javascript=
// #3-1 不同陣列合併
const groupA = ['小明', '杰倫', '阿姨'];
const groupB = ['老媽', '老爸'];
const groupAll = groupA.concat(groupB);
// 使用...淺層複製
const groupAll2 = [...groupA, ...groupB]
// #3-2 物件擴展
// 新增一個物件包含新方法,同時加入原有的方法
const methods = {
fn1() {
console.log(1);
},
fn2() {
console.log(1);
},
}
const newMethods = {
fn() {
console.log(1)
},
...methods
}
console.log(newMethods)
// 結果為
// {
// fn(){console.log(1)},
// fn1(){console.log(1)},
// fn2(){console.log(1)}
// }
// #3-3 轉成純陣列
const doms = document.querySelectorAll('li');
// querySelectorAll 取出的陣列為NodeList陣列,並非純陣列,因此可操作的方法較少
const newDoms = [...doms] // 轉成純陣列
// #4 參數預設值
function sum(a = 1, b = 2) { // 加入預設值避免錯誤
return a + b;
}
console.log(sum(3, 4));
```
## 解構
https://courses.hexschool.com/courses/typescript-30/lectures/50694193
## this指向觀念
https://courses.hexschool.com/courses/vue-20211/lectures/30451587
```javascript=
// #1 一個函式中包含多少參數
var a = '全域'
function fn(params) {
console.log(params, this, window, arguments);
// params 外部傳入的參數
// arguments 所有傳入的參數內容(為Arguments陣列形式)
debugger;
}
fn(1, 2, 3) // params:1; this:window; arguments:[1, 2, 3]
// #2 this 的指向為何
var obj = {
name: '小明',
fn: function(params) {
console.log(params, this, window, arguments);
}
}
obj.fn(1, 2, 3); // this指向obj
// #3 注意:this 的指向相當複雜,大部分情境只需要了解其中一種即可(95%)
// 傳統函式中的 this 只與調用方式有關
var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
callSomeone(); // 全域
// simple call,this會指向全域
// #4 各種運用變化
var obj = {
someone: '物件',
callSomeone() {
console.log(this.someone);
}
}
obj.callSomeone(); //物件 (this指向obj)
// 呼叫一個函式時,若函式前面有物件,則this指向該物件,若無(simple call),this指向全域
var obj2 = {
someone: '物件2',
callSomeone //縮寫帶入
}
obj2.callSomeone(); //物件2 (this指向obj2)
var wrapObj = {
someone: '外層物件',
callSomeone,
innerObj: {
someone: '內層物件',
callSomeone,
}
}
wrapObj.callSomeone(); //外層物件
wrapObj.innerObj.callSomeone(); //內層物件
var obj3 = {
someone: '物件 3',
fn() {
callSomeone(); // simple call
// 通常平常不會這樣去取用 this
}
}
obj3.fn(); //全域
var obj4 = {
someone: '物件 4',
fn() {
// callback function 的 this 大多指向全域
setTimeout(function () {
console.log(this.someone);
});
}
}
obj4.fn();
```
## 箭頭函式
### 箭頭函式縮寫
1. 移除 function,改為在 () 後放 => 符號
2. 若函式僅有1行,移除 {}及 return,改為單行 (箭頭函式會自動帶上return)
3. 若僅有1個參數,可將參數外的 () 移除
```javascript=
const arr = [1, 2, 3, 4, 5]; // 取有餘數的值(單數)
// 傳統
const filterArr = arr.filter(function(item){
return item % 2 // 結果為真值的會回傳出來
})
// 箭頭
const filterArr = arr.filter(item => item % 2);
console.log(filterArr);
```
### 箭頭函式的this綁定
```javascript=
var name = 'Ming'
const person = {
name: '小明',
callName: function () {
console.log('1', this.name); // 1 小明
setTimeout(function () { // callback function 屬於 simple call,this指向全域
console.log('2', this.name); // 2 Ming
console.log('3', this); // 3 Window
}, 10);
// 箭頭函式沒有自己的this,會指向外層函式的作用域 (如下圖)
setTimeout(() => {
console.log('2', this.name); // 2 小明 (this指向person)
console.log('3', this); // 3 {name:'小明', callName: f}
}, 10);
},
}
person.callName();
```

**陷阱**
```javascript=
var name = '全域'
const person3 = {
name: '小明',
callName: () => {
console.log(this.name); // 外層沒有函式,箭頭所在的作用域this指向全域
},
}
person3.callName();//全域
```
```javascript=
var name = '全域'
const person = {
name: '小明',
callMe() {
const callName = () => {
console.log(this.name); // 外層有函式callMe(),箭頭所在的作用域為callMe()的作用域,即 person
};
callName();
}
}
person.callMe(); // 小明
```

**實戰**
避免this指向不如預期的兩種方式
1. 將this先指向其他變數
2. 使用箭頭函式
```javascript=
var someone = '全域';
var obj4 = {
someone: '物件 4',
fn() {
// 方法一:將this先指向其他變數
const vm = this; // vm 在 Vue 中意指 ViewModel
setTimeout(function () {
console.log(vm.someone); // 指向vm的作用域 obj4
});
// 方法二:使用箭頭函式
setTimeout(() => {
console.log(this.someone); // 指向fn()的作用域 obj4
});
}
}
obj4.fn();
```