number、string、boolean、null、undefined javascript
object:{}、[ ]、/$/、Date
function html
當瀏覽器加載html頁面的時候,首先會提供一個全局jsdiam執行的環境java
var num = 12;
var obj = {name:"wjw",age:7);
function fn(){
console.log("勿忘初心方得始終")
}
console.log(fn); // 把整個函數的定義部分(函數自己在控制檯輸出)
console.log(fn()); //把當前函數執行的返回結果(return後面寫的是啥,返回就是啥,若是沒有return,默認返回undefined)
複製代碼
在當前的做用域中,js代碼執行以前,瀏覽器首先會默認的把全部帶var和function的進行提早的聲明或者定義瀏覽器
var num ;
複製代碼
告訴瀏覽器在全局做用域中有一個num的變量了
若是一個變量只是聲明瞭,可是沒有進行變量的定義,那就是undefined
bash
num = 12 //給咱們的變量進行賦值
複製代碼
在預解釋的時候只是提早的聲明閉包
在預解釋的時候,提早的聲明+定義都完成了dom
對於帶var和function關鍵的預解釋的操做仍是不同函數
fn(100,200);//能夠在上面執行,由於預解釋的時候,聲明+定義已經完成了
function fn(num1,num2){
var total = num1 + num2;
console.log(total);
}
複製代碼
例如:開始只對window下得進行預解釋,只有函數執行的時候纔會對函數的進行預解釋ui
用來提供一個js執行的環境 -> 做用域(全局的做用域,私有)this
用來存儲引用數據類型的值 -> 對象存儲屬性名和屬性值,函數存儲的是代碼字符串
在私有做用域中,咱們代碼執行的時候遇到一個變量,首先咱們須要肯定當前它,是不是私有變量,若是是私有的變量,那麼和外面的任何東西都沒有關係;若是不是私有的,則往當前做用域上級做用域進行查找,若是上級做用域也沒有則繼續查找,一直找到window爲止..
(直接目的:讓函數體重的代碼執行),首先會造成一個新的私有的做用域
1.若是有形參,先給形參賦值
2.進行私有做用域中的預解釋
3.私有做用域中的代碼從上到下執行
console.log(total); // undefined
var total = 0;
function fn(num1,num2){
console.log(total); // total 不是私有的,找全局下的total,也就是在這裏出現全部的total其實應該都是
var total = num1 + num2;// 全局的total=300
console.log(total);// 300
}
fn(100,200);
console.log(total);// 300
複製代碼
函數造成一個新的私有的做用域保護了裏面的私有變量不受外界的干擾(修改不了私有的,私有的也修改不了外面的
在全局做用域中,帶var和不帶var的關係?
區別:帶var的能夠進行預解釋,因此在賦值的前面執行不會報錯;不帶var的是不能進行預解釋的,在前面執行會報錯
console.log(num);//undefined
var num = 12;
console.log(num2); // Uncaught ReferenceError:num2 is no defined
num2 = 12;
複製代碼
關係:num = 12 ->至關於給window增長了一個叫作num的屬性名,屬性值12
var num =12 ->首先它至關於給全局做用域增長了一個全局變量num,可是不只如此,它也至關於給window增長了一個屬性名怒,屬性值12
var num = 12;
console.log(num); // 12
num2 = 12;
console.log(num2);// 12 window.num2
複製代碼
私有做用域中出現的一個變量不是私有的,則往上級做用域進行查找,上級沒有則繼續向上級查詢,一直找到window爲止
funtciont fn(){
console.log(total1); // Uncaught ReferenceError:num2 is no defined
total = 100;
}
fn();
console.log(total1)
複製代碼
js中若是不進行任何特殊處理的狀況下,上面的代碼報錯,下面的代碼都不在執行了
in "num" in window 判斷num是否爲window這個對象的一個屬性,是的話返回true,不是返回flase
console.log("name" in obj)
複製代碼
window的預解釋:var num - > window num
if(!("num") in window){ // 「num」 in window ->true
var num = 12
}
console.log(num) -> undefind
複製代碼
匿名函數值函數表達式:把函數定義跌部分當作一個值賦值給咱們的變量(元素的某一個事件)
window下的預解釋 var fn;
fn(); // undefined
var fn = function(){
conslole.log("ok")
}
fun(); // ok
function fn(){
console.log("ok")
}
fn(); // ok
複製代碼
自執行函數: 定義和執行的一塊兒完成了
(function (params) {})(100);
~function (params) {}(100);
+function (params) {}(100);
-function (params) {}(100);
!function (params) {}(100);
複製代碼
function fn(){
// 預解釋:var num;
console.log(num); // ->undefined
return function(){}; // -> 不預解釋
var num = 100
}
fun();
複製代碼
預解釋:var fn ; window.fn; fn-xxxfff000 window.fn-xxxfff00
var fn = 13;
function fn() {
console.log("ok");
}
複製代碼
window 預解釋 聲明+定義 fn = xxxfff11 聲明 var fn; (不須要從新聲明) 聲明(不重複進行)+定義 fn = xxxfff222 fn = xxxfff22
fn(); // ->2
function fn() {console.log(1)}; //-> 2
fn(); // 2
var fn = 10;
fn (); // error 終止了
function fn() {console.log(2)};
fn();
複製代碼
看當前函數是哪一個做用域下定義的,那麼它的上級做用域就是誰
let num =12;
function fn() {
var num = 120;
return function () {
console.log('====================================');
console.log(num);
console.log('====================================');
}
}
var f = fn();
f(); // 這樣就執行了第1次
~function() {
var num = 1200;
f(); // 這樣就執行了第2次
}()
複製代碼
var f = fn()就是把函數fn的運行返回結果賦值給f,fn函數返回的是一個函數,該返回函數的上級做用域爲函數fn
的私有做用域,因此運行f函數console.log(num),num不是f私有做用域的私有變量,須要在上級做用域找,fn的私有做用域含有變量
num,因此都輸出的num爲120。
總結一下,執行函數的做用主要爲匿名和自動執行,代碼在被解釋時就已經在運行了。
(function(){ /* code */ }());
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();
~function(a) {
console.log('====================================');
console.log(a);
console.log('====================================');
}(10)
複製代碼
對象數據類型或者函數數據類型在定義的時候首先都會開闢一個堆內存,堆內存有一個引用的地址,若是外面有變量等知道這個地址,外面就說這個內存被佔用,就不能銷燬。
var obj1 = {name:"張三"};
var obj2 = obj1;
複製代碼
咱們想要讓堆內存釋放/銷燬,只須要吧全部引用它的變量值賦值爲null便可,若是當前的堆內存沒有任何東西唄佔用了,那麼瀏覽器會在空間的時候把它銷燬...
obj1 = null;
obj2 = null;
複製代碼
通常狀況下,函數執行會造成一個新的私有的做用域,當私有做用域中的代碼執行完成後,咱們當前做用域都會主動的進行釋放和銷燬
可是仍是存在特殊的狀況的:
當前私有做用域中的部份內存被做用域之外的東西佔用了,那麼當前的這個做用域就不能銷燬了
a.函數執行返回了一個引用數據類型的值,而且在函數的外面被一個其餘的東西給接收了,這種狀況下造成的私有做用域都不會銷燬
function fn(){
var num = 100;
return function(){
num++;
console.log(num);
}
}
var f = fn(); // fn執行造成這個私有的做用域就不能再銷燬了
複製代碼
b.在一個私有的做用域中給dom元素的事件綁定方法,通常狀況下咱們的私有做用域都不會銷燬
var oDLv = document.getElementById('div1');
~function(){
oDLv.onclick = function(){
}
}() // 當前自執行函數造成一個私有的做用域也不銷燬
複製代碼
c.下述狀況屬於不當即銷燬->fn返回的函數沒有被其它的東西佔有,可是還須要執行一次呢,因此暫時不銷燬,當返回的值執行完成後,瀏覽器會在空閒的時候把它銷燬
function fn(){
var num = 100;
return function(){
}
}
複製代碼
都是自身累加1,在和其餘的值進行運算的時候是有區別的
var i = 5;
console.log(1+i++);//6 i=6
console.log(1+(++i));//6 i=7
console.log(2+(i++)+(++i)+(++i)+(i++));//38
console.log(i);// 9
複製代碼
function fn(){
var i = 10;
return function (n){
console.log(n+(++i));
}
}
var f = fn();
f(10);// 21
f(20);// 32
fn()(10);// 21
fn()(20);// 31
複製代碼
function fn(){
var i = 10;
return function (n){
console.log(n+(++i));
}
}
var f = fn(13);
f(12);// 25
f(24);// 28
fn(15)(12);// 27
fn(16)(13);// 29
複製代碼
咱們在js中主要研究的都是函數中的this
js中的this表明的是當前行爲執行的主體,js中的context表明的是當前行爲的環境(區域)
例如:吳佳瑋在沙縣吃蛋炒餅,this->吳佳瑋 context->沙縣小吃
function 吃飯(){
this->吳佳瑋
}
吳佳瑋.吃飯();
~function(){
吳佳瑋.吃飯();
}();
複製代碼
this是誰和函數在哪定義的和在哪執行的都沒有任何關係:如何的區分 this呢
function fn(){
console.log(this);
}
var obj ={
fn:fn
};
fn(); // this->window
obj.fn();// this->obj
function sum(){
fn();
}
sum();
複製代碼
<div id="div1">有本事點我啊~~</div>
...
<script> document.getElementById("div1").onclick = fn;//fn中的this是#div1 document.getElementById("div1").onclick = fucntion(){ // this->#div1 fn(); // this->window } </script>
複製代碼
var num = 20;
var obj = {
num:30,
fn:(function(num){
this.num *=3;
num+=15;
var num = 45;
return function(){
this.num *=4;
num+=20;
console.log(num);
}
})(num) // 全局變量num的值20賦值給自執行函數的形參,而不是obj下的30,若是想是obj下的30,咱們須要寫obj.num
}
var fn = obj.fn;
fn();
obj.fn();
複製代碼
var oBth = document.getElementById("btn");
var spanNum = document.getElementById("spanNum")
// 利用全局做用域不銷燬原理,把須要的數字定義爲全局的變量
var count = 0;
oBtn.onclick = fucntion(){
count++;
spanNum.innerHTML = cont;
}
// 弊端:在項目中爲防止全局變量之間衝突,咱們通常是禁止或者減小使用全局變量的使用
// 本身造成一個不銷燬的私有做用域來保存咱們須要累加的數字
複製代碼
二、 利用innerHTML的方式處理,每一次點擊時候都先到頁面中獲取最新的值,而後累加,最後把累加的結果從新放回去
var oBth = document.getElementById("btn");
var spanNum = document.getElementById("spanNum")
//
oBtn.onclick = fucntion(){
spanNum.innerHTML++;
}
// 弊端:每一次吧頁面中的內容先轉換爲字符串而後再累加,累加玩以後從新添加回去,
// 當從新的添加的時候瀏覽器重新的渲染一下
複製代碼
三、利用自定義屬性存儲(推薦)
oBth.count = 0;
oBth.onclick = function(){
// spanNum.innerHTML獲取頁面中的內容返回的是一個字符串
spanNum.innerHTML = ++this.count;
}
複製代碼