一日客語:中文:太陽 客語:ngidˋ teuˇ(日頭)
在學建構函式時很常看到this,建構函式內的this會代表新創健的實例(物件),this到底是什麼呢?
函式呼叫傳給函式有哪些?
this又稱為函式背景空間(function context),就是函式所在的背景空間
那就會跟函式如何被呼叫有關係
會隨著呼叫函式不同,他們的this會些許不同
this會是windows物件,那在嚴格模式
下會是undefined
function pig(){
return this}
function dog(){
"use strict"
return this}
pig()//Window
dog()//undefined
// 當使用立即函式
(function pig(){
return this})() //Window
看看瀏覽器顯示畫面:
一般函式:
普通模式(pig())和嚴格模式(dog())
立即函式:
animal物件裡有一個myPig的property name
他的property vlaue 存放一個函式的reference,記得不用括號
像是這樣[Function: pig]
是函數物件
呼叫這函式來看看返回this是什麼吧。
this是myPig
function pig() {
return this;
}
const animal = {
myPig: pig,
};
console.log(animal.myPig); //[Function: pig]
//pig function回傳是this,this是不是animal物件
console.log(animal.myPig() === animal); //true
使用另一個物件crazyanimal來呼叫pig()
此時這個this 會是crazyanimal
const crazyanimal = {
myPig: pig,
};
console.log(crazyanimal.myPig() === crazyanimal);//true
結論:在不同物件內存pig function 的reference
某物件.pig()呼叫函式 ,this會是指某物件
新物件會被當作this
會像是
let 新物件1={
say:function () {
return this; //新物件1
}
let 新物件2={
say:function () {
return this;//新物件2
}
function Pig() {
this.say = function () {
return this;
};
}
let pigA = new Pig();
let pigB = new Pig();
console.log(pigA.say()); //Pig { say: [Function (anonymous)] }
console.log(pigA.say() === pigA);
console.log(pigB.say() === pigB);
以為這樣就結束了嗎???
當建構函式有回傳值,那該怎麼辦
建構函式會以大寫開頭
1.當回傳值:Primitive values (基本型別)
2.當回傳值:物件
會回傳新物件
印出會是Pig { say: [Function (anonymous)]
function Pig() {
this.say = () => '喉喉喉喉';
return 1000;
}
let littlePig = new Pig();
console.log(littlePig);//Pig { say: [Function (anonymous)] }
會回傳return 的物件
印出會是 { }
function Pig() {
this.say = () => '喉喉喉喉';
return {};
}
let littlePig = new Pig();
console.log(littlePig);//{}
const myobj = {
cat1: 'nini',
cat2: 'niki',
};
function Pig() {
this.say = () => '喉喉喉喉';
return myobj;
}
let littlePig = new Pig();
console.log(littlePig);//{ cat1: 'nini', cat2: 'niki' }
Note:
建構器的回傳值是某一個物件時,那麽新物件會被丟棄而回傳那個物件
那如果回傳不是物件則會回傳新物件
筆記:哪一個物件會成為函式背景空間(this)
呼叫
一般函式:this會是windows
建構函式:this會是實例物件
物件方法:this會是方法的物件
但我想要自行設定this呢 ???你可以使用apply、call
建立函式 >> 建構函式
所有函式(object)都具備apply
、call
方法
因為一般函式上一層是建構函式Function他的prototype有apply()和call()方法
apply(當作函式背景空間的物件,用來當作呼叫引數的陣列值)
call(當作函式背景空間的物件,用來當作呼叫引數,但不是陣列值)
是呼叫函式的方法
function Pig() {
console.log('哈囉');
}
Pig.call();//哈囉
Pig.apply();//哈囉
和Pig()一樣都是會呼叫函式
使用call、apply時
此時this會是第一個參數的物件
function Pig() {
console.log(this);
}
Pig();//this會是windows
let obj = {};
Pig.call(obj);//{} 指定的{}
Pig.apply(obj);//{} 指定的{}
可以知道使用call和apply呼叫與一般函式呼叫差異
function person() {
console.log(this.money);
}
let wendy = { money: 1000000000 };
let ann = { money: 300000000 };
person.call(wendy);//1000000000 ,使用這個this會是wendy
person.call(ann);//300000000,使用這個this會是Ann
函數物件.apply(當作函式背景空間的物件,用來當作呼叫引數的陣列值)
Pig.apply(animal,[10,9,8,7]
Function.prototype.call
函數物件.call(當作函式背景空間的物件,用來當作呼叫引數,但不是陣列值)
Pig.call(animal,10,9,8,7)
如下:
let wendy = {
money: 1000000000,
sleep: function () {
console.log(this.money);
},
};
let ann = { money: 300000000 };
console.log(wendy.sleep()); //印出1000000000
//想指定this為ann時
console.log(wendy.sleep.apply(ann)); //印出300000000
當function 有參數時
function person(value1, value2) {
console.log('value1:', value1);
console.log('value2:', value2);
console.log(this.money);
}
let wendy = {
money: 1000000000,
};
let ann = { money: 300000000 };
person.call(wendy);
//結果
//value1: undefined
//value2: undefined
//1000000000
可以使用第二個參數為引數
apply是要使用陣列
function person(age, score) {
console.log('age:', age);
console.log('score:', score);
console.log(this.money);
}
let wendy = {
money: 1000000000,
};
let ann = { money: 300000000 };
person.call(wendy, 10, 1000000);
//結果
//age: 10
//score: 1000000
//1000000000
person.apply(wendy, [10, 1000000]);
//結果
//age: 10
//score: 1000000
//1000000000
mdn:
箭頭函式並不擁有自己的 this 變數;使用的 this 值來自封閉的文本上下文,也就是說,箭頭函式遵循常規變量查找規則。因此,如果在當前範圍中搜索不到 this 變量時,他們最終會尋找其封閉範圍。
this會到(lexical scoping)scope找this,不是以呼叫方式來看
Arrow functions do not bind their own this, instead, they inherit the one from the parent scope, which is called "lexical scoping".
不是使用箭頭函式時
如下:
此時this是animal
let animal = {
myfunction: function () {
return this;
},
};
console.log(animal.myfunction() === animal); //true
箭頭函式時,this是window
let animal = {
//此時this是window)
myfunction: () => this,
};
console.log(animal.myfunction() === window); //true
今日結束~
Day 21:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (1)
Understanding "this" in javascript with arrow functions
忍者開發技巧探秘第二版