作用域
js中我們代碼運行的環境叫做--作用域
作用域:全局作用域(可以加window.)--window;
私有作用域--函數執行時產生的作用域;
在全局作用域先定義的變量或者(系統自帶的一些方法),相當于給全局window增加了一些屬性名,我們可以直接寫或者window.a都沒有問題,不寫默認window. ;
console.log(a);--a is not defined;--預解釋的時候沒有找到a;
a=12;
預解釋:js代碼執行之前,帶var和function關鍵字的提前聲明declare(定義),然后找完了,從上往下執行;
預解釋只發生在當前作用域
var的預解釋:
----代碼執行之前先聲明(只聲明并沒有賦值--定義undefined)
----從上往下執行代碼
----聲明的變量和值進行關聯
function的預解釋:
----代碼執行前先聲明declare,但是和var不同的是,funciton連定義也完成了;
----函數作用域中,沒有聲明只是賦值的話,改變的是全局作用域下的變量;
在函數作用域下,也要進行預解釋,如果函數內部有var和funciton的聲明變量,形成函數的私有作用域,如果找不到,就往上一級的作用域里找,一直到window下的作用域,如果還找不到,就會報一個未定義的錯誤;
1預解釋發現相重的,不重復聲明;(只聲明不代表不定義--
遇到函數fn=3;function fn(){};(就是所謂的函數的優先級高)執行 的是函數的)函數不僅聲明還定義了;;
2預解釋是不管條件的;
3預解釋只解釋等號左邊的,不預解釋右邊的;var fn=function a(){};
4function中return后面的返回值(包括函數),不進行預解釋;
5預解釋只發生在一個腳本塊中;
6函數中的形參相當于私有作用域下聲明了一個變量,進行了預解釋;
7閉包格式的函數--不進行預解釋的
預解釋:找var和function
var a=12;
function a(){
var a=13;console.log(a);
}
a=a();
console.log(a);
聲明了a,遇到function發現已經聲明了,function還有定義,
預解釋聲明--var a;a=function(){};
執行:a=12;a=12(){}--number is not function
作用域:
函數沒有執行的時候沒有任何的意義
開辟一個新的內存,里面存儲的是我們看上去像代碼的字符串,然后函數里面存儲的是對新的內存地址的訪問
函數執行的時候,會形成一個私有的作用域(和我們開始的window類似),首先也是預解釋,接下來從上往下執行代碼
--正常情況下,我們一個function的生命周期:
出生:從預解釋開始聲明加定義-開辟一個新的內存塊,讓函數名存貯對這個內存塊的引用地址
成長:函數執行,形成一個私有作用域,然后里面開始類似與window的新一輪預解釋,代碼從上到下執行;
死亡:一般情況下,私有作用域下的代碼完成后,整個私有作用域就銷毀了;
函數執行形成一個私有作用域,保護里面的變量不受外界的干擾(外面拿不到也修改不了)--這種機制叫做閉包;
--一個function運行的時候,會形成一個私有的作用域,如果這個沒有返回一個function(外面沒有其他的東西占用他的內存的話),這個私有作用域執行完會自動銷毀了,但是如果返回了一個funciton,而且之后函數外面還用到了這個function的話,那么這個函數是銷毀不了的;--(一個函數是從形參開始執行的)
this:
[1]this和在哪定義和在哪執行沒有半毛錢關系,和(函數執行時候的主體--主體是誰就是誰<主體就是.前面的>)有關系,沒有的話默認的是window,而且this只出現在function中&或者全局作用域下;
[2]綁定事件:誰綁定的主體就是誰
[3]閉包:主體是window
改變this關鍵字的方法
<1>call和apply
函數體.call(主體,形參,值,值)--一個一個
函數體.apply(主體,[形參,值,值])--數組的形式
call方法的第一個參數,是指函數運行是this的指向
從第二個參數開始,這些參數一次傳給函數,傳給函數的參數是以散列的方式存在的
apply方法最多只有兩個參數,第一個參數和call相同,第二個參數是一個集合(數組),把整個集合傳給函數方法,第二個參數相當于函數的arguments;
call的特殊用法:
fn.call(null)--如果一個方法和函數不能確定主體是誰,或者this指向了一個不存在的對象(null或undefined)則this指的是window;
apply的特殊用法:--找出數組中最大值和最小值
Math.min(12,3,34,5,3,7,8,4,23,15)--Math.min的參數是一個個傳進去的(散列式的),不能是數組;
Matn.min(a)--錯誤的,不能是一個變量;
Math.min.apply(null,a);--用apply傳遞的第二個參數是一個集合特點,把a這個集合,以整體的方式傳給了min;
<2>傳遞this
主體下聲明var that=this
函數中的 this-->that(執行的時候沒有聲明向上級找--找到的是主體中的this)
用instanceof 不能夠嚴格的判斷一個實例是不是這個類的實例
function isArray(obj){
return Object.prototype.toString.call(obj)=="[object Array]";
}
面向對象:
實例創建對象:
(1)單例模式--需要手動一個個創建;(避免使用全局變量或者全局的方法導致沖突,我們把需要的方法和變量當作對象數據類型的屬性名和屬性值存起來,每次執行的時候,對象.屬性名就可以了,解決全局下的沖突問題);-----命名空間:我們把創建的那個對象名稱之為命名空間;
第二種情況:var obj=(function(){
var a="";
function check(){
};
function submit(){
};
return {check:check,submit:submit};
})();
obj.check();
obj.submit();
(2)工廠模式--為了解決單例模式一個個生產的問題,實現批量生產
構造一個函數,函數里var一個obj對象,把方法和變量當作對象數據類型的屬性名和屬性值存起來,然后把obj返回;
(3)構造函數--實例識別(差異)
對象、類、實例
js對象是一種復合類型,通過變量名存儲和訪問,對象是一個無序的屬性集合
類是對象的細分,只需要new操作符就可以實現一個實例;
工廠模式和構造函數的區別:
不需要手動創建obj對象了,而且也不用return obj對象了;
原先obj統一替換成this(this是誰)
[4]跟創建的實例有關系,創建的實例是誰,this就是誰
執行:定義變量=new 函數名(參數值)
我們把執行函數的時候,用new創建的方式稱之為構造函數模式(實例創建方式),通過這種方式,我們把原先的那個函數稱之為類,把返回的結果(就是var的那個變量)稱之為這個類的一個實例
構造函數new執行過程:返回的實例也是一個對象數據類型;
也就是說,new一個函數的時候,首先會默認創建一個對象,也就是我們創建的實例(變量);
接下來會以實例(this)作為上下文,把對應的屬性存起來;
返回的時候,實例就擁有了這些屬性名和屬性值;
默認的把我們創建的對象給我們的實例(變量名)--也就是我們創建的實例就是我們要的對象,換句話說this就是我們創建的這個實例
檢測實例:instanceof--用來檢測某一個實例是否是屬于某個類的,屬于返回true,不屬于返回false;Js內置類:String,Object,Array,Number,Math,Date,RegExp
Js中所有的對象數據類型都是內置Object類的一個實例
(4)基于構造函數的原型鏈模式:--解決產品差異化的同時,有相同的部分還可以共享----------構造函數不足:很多通用的方法沒有實現共享,函數里邊的相同方法一樣才對,但是現有的構造函數模式,實現不了;
將需要共享的屬性寫在原型鏈prototype上,這樣prototype上所定義的屬性和方法就可以被一個類的實例共享了;
prototype原理:每一個function都有一個天生自帶的屬性prototype,如果不是構造函數(new 函數)的話,這個函數沒有任何意義;
prototype存儲的是一個對象數據類型,有自己的內存塊,并且這個內存塊上又有兩個自帶的屬性constructor,__proto__;constructor是prototype這個對象數據類型特有的,而_proto_是所有對象數據類型都有的;
當我們new一個函數的時候,函數變成了類,并且返回一個實例,這個實例是對象數據類型的,所以有__proto__這個自帶的屬性,并且這個屬性指向的是我們函數里面prototype自己的那個內存地址----所以我們變量(new)除了擁有函數里面自帶的私有屬性的時候,擁有了原型鏈__proto__屬性;
一個對象被創建時,它的 __proto__ 屬性和內部屬性[[Prototype]]指向了相同的對象 (也就是它的構造函數的prototype屬性).改變__proto__ 屬性的值同時也會改變內部屬性[[Prototype]]的值;
我們在調用實例上的屬性名的時候,遵循這樣順序:先找私有的,私有的沒有,在通過__proto__所在的類的原型上,如果在私有的中找到了,就不再往下找了;
hasOwnProperty--檢測某個實例上是否存在某個屬性(是私有屬性才有效,原型鏈上的無法檢測)
isPrototypeOf--檢測原型鏈的對象是否存在于指定的對象實例中
Fn.prototype.isPrototypeOf(實例)------true
Fn.isPrototypeOf--------------------------false
hasOwnProperty()與for in的區別
1 in 判斷某個對象中有沒有某個屬性--不管私有還是共有的;
(屬性名 in 實例)
2 hasOwnProperty()只能檢測自定義屬性,無法檢測原型鏈屬性。
我們常用的一些內置的類 如:String Array 等提供的方法都是在原型上的
"str".hasOwnProperty("split");//false
String.prototype.hasOwnProperty("split");//true
只檢測公有的屬性--return !obj.hasOwnPorperty(key)&&(key in obj);
js中我們常用的this的幾種情況:
【】給元素綁定事件oDiv.onclick=function(){};this就是oDiv;
【】閉包(function(){this是window})();
【】函數執行前的主體 fn()-->window obj.fn()-->obj;
【】當一構造函數執行的時候,this就是我們創建的那個實例;
所有的對象數據類型都是內置Object類的一個實例
- 1. KanCloud快捷鍵
- algate.github.io的網站建設
- algate.github.io基礎完善
- 如何在github上展示作品——為你的項目生成一個快速訪問的網址
- Github README.md 添加圖片
- git上傳github常用命令
- WEB開發文檔
- 工具相關文檔說明
- GulpJs開發文檔
- 安裝Gulp詳細教程
- 如何上傳到github
- 服務端相關文檔
- tomcat配置多域名多端口訪問
- Vue遇到的那些大坑
- vue-bulid新建問題解決方案
- vue-prev功能實現方案優劣(element)
- 常用組件使用和功能實現
- 1-文件上傳功能
- 2-select插件實現利弊
- 3-實現分步驟流程效果
- ES6-export與export default遇到的坑
- require.context()-route去中心化管理
- webpack.ensure(webpack代碼分割)
- angular爬-跪著也要爬完
- 新建遇到的問題
- 常用angular核心知識
- React初生牛犢不怕虎
- react初次見面之泥坑深譚
- react+webpack+es6精簡版HelloWorld
- create-react-app創建失敗
- create-react-app不歸路
- react用到的組件module
- react-hot-loader
- JavaScript成長之路
- Js進階
- Js模塊化編程:require.js的用法
- 淺談前端架構
- Js常見問題匯總
- 瀏覽器渲染原理及解剖瀏覽器內部工作原理
- 雅虎前端優化的35條軍規
- 常見問題描述-面試常問
- 前端性能優化-algate
- http狀態碼詳解
- 作用域,閉包,面向對象
- Js基礎知識
- Js基本功必須扎實
- 各個瀏覽器加載icon
- html特殊標簽和屬性的說明
- 個人資源總結
- 個人簡歷-絕對真實有效
- Jekyll博客創建
- Jekyll開始創建
- Jekyll文檔說明
- jekyll-paginate分頁問題
- HEXO博客創建
- es6新用法解析以及使用
- 神奇的三個點:...
- 幾大類
- coding創建hexo
- sublime相關配置
- Atom使用