日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

原型和闭包

發布時間:2023/12/13 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 原型和闭包 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原型和閉包

一切皆對象

一切皆對象(類型值除外)

undefined, number, string, boolean屬于簡單的值類型

函數、數組、對象、new Number(10)都是對象。他們都是引用類型

Null是基本數據類型,不是引用數據類型
基本數據類型的值就是它本身的值,引用數據類型是存放的對這個對象引用的指針,Null本身的值就是Null,所以不是引用類型

不同的對象在底層都表示為二進制,在 JavaScript 中二進制前三位都為 0 的話會被判
斷為 object 類型, null 的二進制表示是全 0,自然前三位也是 0,所以執行 typeof 時會返回“ object ”。

http://www.cnblogs.com/xiaoheimiaoer/p/4572558.html

判斷值類型的類型用typeof,引用類型的類型用instanceof

javascript為弱類型,里一切皆是對象,對象里面都是屬性,而它的方法也是一種屬性,用鍵值對的形式來表示,且javascript中的對象可以隨意擴展屬性,沒有class的約束。

簡單示例

var a1={b:10,c:function(n){alert(this.a+n);},d:{car:"000000",long:"五十"} };

雖然函數是一種對象,但函數和對象那個之間更像是一種相互生成的關系

對象都由函數來創建,我們平時所寫的var let等其實是一種“語法糖”其本質還是函數

prototype原型

每一個函數都有一個屬性叫prototype

prototype的屬性值是一個對象,只有一個默認的叫constructor屬性,指向函數本身,而還我們可以自己采用自定義的形式在prototype中新增自己的屬性

function F1(){} F1.prototype.age="1982"; F1.prototype.sex=function(){return "man"; };

而這樣做的作用就要聯系到jQuery了

var $("div"); $div.attr('myAge','18');

上面代碼中,$('div')返回的是一個對象,而對象被函數創建的而他的實現過程如下

myjQuery.prototype.attr=function(){}; $('div')=new myjQuery();

其本質就是

function F1(){} F1.prototype.age="1982"; F1.prototype.sex=function(){return "man"; }; var f2=new F1(); console.log(f2.age); console.log(f2.sex());

F1是一個函數,f2對象是從F1函數new出來的,這樣f2對象就可以調用F1.prototype中的屬性。

因為每個對象都有一個隱藏的屬性——“proto”,這個屬性引用了創建這個對象的函數的prototype。即:

f2.__proto__ === F1.prototype

這里的"______proto_______"成為“隱式原型”

__ proto__ 原型

每個函數function都有一個prototype,即原型。同時每個對象都有一個__ proto__

其指向創建該對象的函數的prototype

個__ proto __是一個隱藏的屬性,javascript不希望開發者用到這個屬性值,有的低版本瀏覽器甚至不支持這個屬性值

自定義函數的prototype都是被Object創建,所以它的_ _proto__指向的就是Object.prototype

但是Object.prototype確實一個特例——它的__ proto__指向的是null,切記切記

函數也有原型

function fn(x,y){return x+y; }; console.log(fn(10,20));var f1= new Function("x","y","return x+y;"); console.log(f1(8,7));

第二種為new Function僅作理解使用,Function作為函數,也是一種對象,所以也有 __ proto__ 屬性,而函數本身是被Function創建,所以Function是被自身創建,他的 __ proto __指向了自身的Prototype。

同理Function.prototype指向的對象,它的__ proto __也指向Object.prototype

instanceof

instanceof 用于對引用類型的判斷

Instanceof的判斷隊則是:

function Foo(){} var f1=new Foo();console.log(f1 instanceof Foo);//true console.log(f1 instanceof Object);//true

設第一個變量為A,設第二個函數為B

沿著A的__ proto__這條線來找,同時沿著B的prototype這條線來找,如果兩條線能找到同一個引用,即同一個對象,那么就返回true。如果找到終點還未重合,則返回false

將前面的整合為整體如下圖,通過此圖,可以捋清為何返回值為true了

其實instanceof表示的就是一種繼承關系,或者原型鏈的結構

繼承

javascript中的繼承是通過原型鏈來體現的

js是原型繼承,C#是類型繼承。
原型繼承比類型繼承更加靈活,但是又不如類型繼承可控

function foo(){} var f1=new foo();f1.a=10;Foo.prototype.a=100; Fpp.prototype.b=200;console.log(f1.a);//10 console.log(f1.b);//200

f1是Foo函數new出來的對象f1.a是f1對象的基本屬性而非。b從Foo.prototype得來

f1.__ proto __指向的是Foo.prototype

**訪問一個對象的屬性時,先在基本屬性中查找,如果沒有,再沿著__ proto__這條鏈向上找,這就是原型鏈 **

訪問f1.b時,f1的基本屬性中沒有b,于是沿著__ proto__找到了Foo.prototype.b

可使用hasOwnProperty區分一個屬性是基本屬性還是原型

原型的靈活性

對象屬性可以隨時改動

在對象或函數new出來后可以隨時加屬性

繼承方法不合適也可以隨時修改

缺少你所要用的方法時,可以隨時去創建

執行上下文

  • 變量、函數表達式——變量聲明,默認賦值為undefined;
  • this——賦值;
  • 函數聲明——賦值;

這三種數據的準備情況我們稱之為“執行上下文”或者“執行上下文環境”。

函數每被調用一次,都會產生一個新的執行上下文環境。因為不同的調用可能就會有不同的參數

另外一點不同在于,函數在定義的時候(不是調用的時候),就已經確定了函數體內部自由變量的作用域

大白話理解:在執行代碼之前,把將要用到的所有的變量都事先拿出來,有的直接賦值了,有的先用undefined占個空

了解了執行上下文環境中的數據信息,你就不用再去死記硬背那些可惡的面試題了

this

? 在函數中this到底取何值,是在函數真正被調用執行的時候確定的,函數定義的時候確定不了,因為this的取值是執行上下文環境的一部分,每次調用函數,都會產生一個新的執行上下文環境。

  • 構造函數

    所謂構造函數就是用來new對象的函數。其實嚴格來說,所有的函數都可以new一個對象,但是有些函數的定義是為了new一個對象,而有些函數則不是。另外注意,構造函數的函數名第一個字母大寫(規則約定)

  • 函數作為對象的一個屬性

    如果函數作為對象的一個屬性時,并且作為對象的一個屬性被調用時,函數中的this指向該對象

  • 函數用call或者apply調用

    當一個函數被call和apply調用時,this的值就取傳入的對象的值。

  • 全局 & 調用普通函數

    全局環境下,this永遠是window

    普通函數在調用時,其中的this也都是window

  • 其實,不僅僅是構造函數的prototype,即便是在整個原型鏈中,this代表的也都是當前對象的值。

    執行上下文棧

    ? 執行全局代碼時,會產生一個執行上下文環境,每次調用函數都又會產生執行上下文環境。當函數調用完成時,這個上下文環境以及其中的數據都會被消除,再重新回到全局上下文環境。處于活動狀態的執行上下文環境只有一個。

    其實這是一個壓棧出棧的過程——執行上下文棧

    作用域

    通常大家認為“javascript沒有塊級作用域”。所謂“塊”,就是大括號“{}”中間的語句

    javascript除了全局作用域之外,只有函數可以創建的作用域。

    ? 所以,我們在聲明變量時,全局代碼要在代碼前端聲明,函數中要在函數體一開始就聲明好。除了這兩個地方,其他地方都不要出現變量聲明。而且建議用“單var”形式

    作用域有上下級的關系,上下級關系的確定就看函數是在哪個作用域下創建的

    作用域最大的用處就是隔離變量,不同作用域下同名變量不會有沖突

    作用域在函數定義時就已經確定了。而不是在函數調用時確定

    ? 作用域只是一個“地盤”,一個抽象的概念,其中沒有變量。要通過作用域對應的執行上下文環境來獲取變量的值。同一個作用域下,不同的調用會產生不同的執行上下文環境,繼而產生不同的變量的值。所以,作用域中變量的值是在執行過程中產生的確定的,而作用域卻是在函數創建時就確定了。

    所以,如果要查找一個作用域下某個變量的值,就需要找到這個作用域對應的執行上下文環境,再在其中尋找變量的值

    自由變量到作用域鏈

    將變量在作用域外聲明在作用域中調用的變量為自由變量

    要到創建這個函數的那個作用域中取值——是“創建”,而不是“調用”,無論函數將在哪里調用

    閉包

    閉包,可理解為:函數作為返回值,函數作為參數傳遞

    有些情況下函數在被調用完后其上下文環境不會被銷毀,如返回值唯一個函數,函數的特別之處在于可以創建一個獨立的作用域

    使用閉包會增加內容開銷,只有在所有閉包相關作用域執行完畢后才會銷毀

    圖片來源于網絡

    轉載于:https://www.cnblogs.com/baiyang2292/p/11175619.html

    總結

    以上是生活随笔為你收集整理的原型和闭包的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。