1. 程式人生 > 其它 >Cookie/Session和token是什麼

Cookie/Session和token是什麼

函式的執行過程

  1. 為函式建立一個執行環境

  2. 複製函式的 [[scopes]] 屬性中的物件構建起執行環境的作用鏈域

  3. 建立函式活躍物件並推入執行環境作用鏈域的前端

  4. 執行程式碼

  5. 銷燬執行環境和活躍物件(閉包情況下活躍物件仍被引用沒被銷燬)

函式的宣告方式

表示式宣告

表示式宣告時,其實分為兩步,先宣告變數,再把函式賦值給這個變數,後面的函式作為值並不會發生宣告提升

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);