筆記:Prototypical Networks for Few-shot Learning
函式的執行過程
-
-
複製函式的 [[scopes]] 屬性中的物件構建起執行環境的作用鏈域
-
建立函式活躍物件並推入執行環境作用鏈域的前端
-
執行程式碼
-
函式的宣告方式
表示式宣告
表示式宣告時,其實分為兩步,先宣告變數,再把函式賦值給這個變數,後面的函式作為值並不會發生宣告提升
var fn=function (){
}
var fn =function fn(){
}
字面量宣告
function fn(){
}
函式的引數
注意:
形參可以理解為在函式體內部聲明瞭一個新的變數
形參與實參的關係可以理解為形參=實參(注意:實參是引用資料型別時,實際傳的是引用資料型別的地址)
var a=1;
function fn(a){
a=2; //fn內參數傳遞可以理解為1=2,並不會修改外部作用域a的值,只是將1當一個變數使用;
}
fn(a)
var a=[1]; //假設[1]的地址為0X100,0x100指向[1];
function fn(a){
a=2; //fn內參數傳遞可以理解為0x100=2,並不會修改外部作用域a的地址,只是將0x100當一個變數使用;
//假設[2]的地址為0x200
a=[2]; //fn內參數傳遞可以理解為0x100=0x200,0x200指向[2];
}
fn(a)
引數分類
函式的引數分為形參和實參:
形參可以理解為在函式體內部聲明瞭一個新的變數
,形參的值可以理解為拷貝了實參的值
實參是呼叫作用域內對應的同名數據(可以是任何型別)
形參和實參可以個數不相等,當形參的個數大於實參時,多餘的形參為undefined,當實參的個數大於形參時,除了arguments有變化外沒有任何影響
var a=1,b=1;
function fn(a,b){
}
fn(a,b) //把變數a和b的值當作實參傳給形參
//類似這樣
function fn(){
var a=a,b=b; //把變數a,b的值賦值給形參
}
函式的引數表示式
函式的形參如果有實參傳值則為實參的值,如果沒有則為表示式的值
var a=1,b=2;
function fn(c=a?b:a,d=b){
console.log(c,d);
}
fn(a)
函式的返回值
函式的return可以理解為函式呼叫表示式==return;
閉包函式
閉包是什麼?
深層理解:
閉包是擁有外層函式物件
所對應的活動物件引用
的函式物件
一般理解:
閉包是巢狀函式的內部函式,包含外部函式的變數(物件)的函式物件
閉包的形成
https://zhuanlan.zhihu.com/p/66701792
函式呼叫的時候會在棧空間開闢一塊空間,這個空間叫函式執行環境,一般函式呼叫完畢出棧後,其內的活躍物件會被垃圾回收機制回收,但是當這個活躍物件被其他函式的scope引用時,活躍物件將無法釋放,這樣就形成了閉包(此時這個活躍物件只能被閉包函式找到)
閉包函式的執行過程
當閉包函式呼叫進棧時,產生一個新的活躍物件,這個活躍物件scope屬性的__parent__
指向外部函式產生的活躍物件,當我們要修改某個變數(或引用型別)的時候,在當前作用域找不到,就往上一級找,一直到找到後修改這個變數(或引用型別)
當閉包呼叫結束出棧,閉包自身的活躍物件會被銷燬,但是外部函式的活躍物件仍然被閉包函式自身的scope引用,依舊無法釋放.
閉包程式碼加圖分析
function addAge(){
var age = 21;
return function(){
age++;
console.log(age);
}
}
var clourse = addAge();
clourse();
第一階段
第二階段
第三階段
第四階段
第五階段
遞迴函式
定義
直接或間接的呼叫自身的函式稱為遞迴函式
分析
首先,函式的return可以理解為函式呼叫表示式==return;
分析如下程式碼:
function fn(n){
if(n==1){
return n;
}
return n+fn(--n);
}
console.log(fn(5));
函式執行過程為:
fn(5)=5+fn(4);
fn(4)=4+fn(3);
fn(3)=3+fn(2);
fn(2)=2+fn(1);
fn(1)=1;
//綜上所述
fn(5)=5+4+3+2+1;
建構函式
建構函式通過new關鍵字呼叫
new Person()
建構函式當成普通函式圖解
new做的事情圖解
1、開闢記憶體空間(堆)
2、this指向該記憶體(讓函式內部的this)
3、執行函式程式碼
4、生成物件例項返回
new關鍵字做了什麼:
1.以建構函式的prototype屬性為原型,建立新物件;
2.使用指定的引數呼叫建構函式,並將 this
繫結到新建立的物件
3.如果建構函式沒有手動返回物件(引用型別),則返回第一步建立的物件(例項),否則返回手動設定的返回值
實現一個簡單的new方法
// 構造器函式 let Parent = function (name, age) { this.name = name; this.age = age; }; Parent.prototype.sayName = function () { console.log(this.name); }; //自己定義的new方法 let newMethod = function (Parent, ...rest) { // 1.以建構函式的prototype屬性為原型,建立新物件; let child = Object.create(Parent.prototype); // 2.使用指定的引數呼叫建構函式,並將 `this` 繫結到新建立的物件 let result = Parent.apply(child, rest); // 3.如果建構函式沒有手動返回物件(引用型別),則返回第一步建立的物件(例項),否則返回手動設定的返回值 return typeof result === 'object' ? result : child; }; //建立例項,將建構函式Parent與形參作為引數傳入 const child = newMethod(Parent, 'echo', 26); child.sayName() //'echo'; //最後檢驗,與使用new的效果相同 child instanceof Parent//true child.hasOwnProperty('name')//true child.hasOwnProperty('age')//true child.hasOwnProperty('sayName')//false child.__proto__===Parent.prototype//true
1 let a=1,b=2,c=3; 2 function fn(a,b,c){ 3 } 4 function new1(...str){ 5 //1.建立一個空的簡單JavaScript物件(即`{}`) 6 let obj={}; 7 //2.為步驟1新建立的物件新增屬性`__proto__`,將該屬性連結至建構函式的原型物件 8 obj.__proto__=fn.prototype; 9 //3.將步驟1新建立的物件作為`this`的上下文 10 let result=fn.call(obj,...str); 11 //4.如果該函式沒有返回物件,則返回`this` 12 return result instanceof Object==='object'?fn():obj; 13 } 14 let fn1=new1(a,b,c); 15 console.log(Object.getPrototypeOf(fn1)===fn.prototype);