JS基礎難點總結(函式作用域,變數提升,物件,建構函式,this)全!!!

Monster1010發表於2019-10-31

JavaScript的組成

ECMAScrpit - 描述了語言的基本語法和資料型別  
BOM - 瀏覽器物件模型:一套操作瀏覽器功能的API,可以通過BOM彈框,獲取螢幕解析度  
DOM - 文件物件模型:一套操作頁面元素的API,可以操作文件樹上的節點
複製程式碼

變數

什麼是變數

變數是計算機記憶體中儲存資料的識別符號,根據變數名可以獲取記憶體中儲存的資料   
使用變數可以方便的獲取或修改記憶體中的資料
複製程式碼

如何使用變數

用var來宣告
var a = 'monster'
注意:js中的變數如果不用var來宣告,如: b = 'monster' ,b就是全域性變數(全域性物件屬性)

var a = b = 'monster'
在預編譯時會被解析為 
var a;
a = 'monster';
b = 'monster'
複製程式碼

這時b就是一個全域性變數,但是不推薦使用

函式

實參和形參

// 函式內部是一個封閉的環境,可以通過引數的方式,把外部的值傳遞給函式內部
// 帶引數的函式宣告
function 函式名(形參1, 形參2, 形參3...) {
  // 函式體
}
// 帶引數的函式呼叫
函式名(實參1, 實參2, 實參3); 
形參1 = 實參1
形參2 = 實參2
複製程式碼
var x = 5, y = 6;
fn(x,y); 
function fn(a, b) {
  console.log(a + b);
}
//x,y是實參,函式執行的時候會把x,y複製給a,b;函式內部是複製後的新值,無法改變外部的x,y
複製程式碼

函式的返回值

1.//宣告一個帶返回值的函式
function 函式名(形參1, 形參2, 形參3...) {
  //函式體
  return 返回值;
}
2.//用變數接受這個返回值
var 變數 = 函式名(形參1, 形參2, 形參3...)
函式的呼叫結果就是返回值,因此我們可以直接對函式呼叫結果進行操作。
複製程式碼

arguments

函式內部 arguments 物件:可以通過arguments獲取函式的實參。 例:可以用來求 任意數字的和

1. 可以通過arguments獲取函式呼叫時傳入的實參
function test(a,b,c) {
    console.log(arguments)
}
2. 求任意個數的最大值
function getMax() {
    max = arguments[0];
    for(var i = 0; i < arguments.length; i++) {
        if(max < arguments[i]) {
            max = arguments[i];
        }
    }
    return max;
}

var max = getMax(2,10,4,67,29)   //傳入不定個數的陣列
console.log(max)
複製程式碼

函式是一種資料型別

function fn() {}
console.log(typeof fn);
複製程式碼
  • 函式作為引數
    因為函式也是一種型別,可以把函式作為兩一個函式的引數,在另一個函式中呼叫
  • 函式作為返回值
    因為函式是一種型別,所以可以把函式作為返回值從函式內部返回
function fn(b) {
    var a = 10;
    return function() {
        alert(a + b);
    }
}
fn(15)();
複製程式碼

作用域

作用域:變數可以起作用的範圍
複製程式碼

全域性變數和區域性變數

 全域性變數

 在任何地方都可以訪問到的變數就是全域性變數,對應全域性作用域

 區域性變數

 只在固定的程式碼片段內可訪問到的變數,最常見的例如函式內部。對應區域性作用域(函式作用域)
複製程式碼

變數退出作用域之後會銷燬,全域性變數關閉網頁或瀏覽器才會銷燬

function fn() {
    var num = 5;
}
console.log(num)   //num is not defined
//函式內部定義的變數num是區域性變數,在外部不可以訪問
複製程式碼

作用域鏈

只有函式可以製造作用域結構,那麼只要是程式碼,就至少有一個作用域,即全域性作用域。
凡是程式碼中有函式,那麼這個函式就構成另一個作用域。
如果函式中還有函式,那麼在這個作用域中就又可以誕生一個作用域。
複製程式碼

將這樣的所有的作用域列出來形成作用域鏈 : 函式內指向函式外的鏈式結構。程式碼在執行時,先在函式內部找變數,找不到再去函式外找

 // 全域性作用域 -- 0級作用域鏈
var num = 5;
function f1() {
  // f1 區域性作用域   -- 1級作用域鏈
  // var num = 15;
  function f2() { 
    // f2 區域性作用域  -- 2級作用域鏈
    console.log(num);
  }
  f2();
}
f1();
複製程式碼

預解析 -- 變數提升

預解析過程:

  1. 把變數的宣告提升到當前作用域的最前面,只會提升宣告,不會提升賦值
  2. 把函式的宣告提升到當前作用域的最前面,只會提升宣告,不會提升呼叫
  3. 先提升var,再提升function
  4. 提升完後其他程式碼位置不變
1var a = 25;
    function abc() {
        alert(a); 
        var a = 10;
    }
    abc();
    
   預解析後如下:
    var a;
    function abc() {
        var a;
        alert(a);
        a = 10;
    }
    a = 25;
    abc();  //ndefined;
複製程式碼
2:
    var a = 18;
    f1();
    function f1() {
      var b = 9;
      console.log(a);
      console.log(b);
      var a = '123';
    }
    
   預解析後如下:
    var a;
    function f1() {
        var b;
        var a;
        b = 9;
        console.log(a);
        console.log(b);
        a = '123';
    }
    a = 18;
    f1();
    // undefined 
    // 9
複製程式碼

物件

為什麼要有物件

function printPerson(name, age, sex....) {
}
// 函式引數很多的化,可以傳入物件簡化
function printPerson(person) {
    console.log(person.name)
}
複製程式碼

什麼是物件

現實生活中,萬物皆物件,比如一輛車,一部手機。
物件是一個具體的事物,事物就會有特徵和行為。
js中的物件是生活中物件的抽象,可以把JavaScript中的物件想象成鍵值對,其中值可以是資料(物件字面量)和函式。
物件的行為和特徵:
    特徵---屬性
    行為---方法

思考:狗是物件嗎?我認為狗不是物件,狗描述了一類事物,但我家的薩摩耶是一個物件
複製程式碼
物件和函式有相似性,函式封裝了程式碼,可重用;物件封裝了一組屬性和方法,同樣可重用。
複製程式碼

物件建立方式

物件字面量

建立小明物件,小明具有的 屬性有  name,age等,方法有 打招呼
複製程式碼
var o = {
  name: 'zs',
  age: 18,
  sex: true,
  //在方法中如何使用物件的屬性呢?用this.
  //this代表的是當前物件
  sayHi: function () {
    console.log(this.name + '你好');
  }
  }

//訪問物件的屬性    console.log(o.name) 或 console.log(o['name'])
//訪問物件的方法    o.saiHi()
複製程式碼
思考:函式和方法的區別:方法是物件的函式;通過 o.sayHi()呼叫
複製程式碼

new Object()

通過new來建立建構函式

var person = new Object();   //new Object()呼叫建構函式;在記憶體中建立了一個空的物件,
然後可以通過動態的方式給物件新增屬性和方法。體現了js的動態性
person.name = 'monster'
person.sayHi = function() {
console.log('Hello,everyBody');
}
複製程式碼

工廠模式批量建立物件

function createPerson(name,age,job) {
    var person = new Object();
    person.name = name;
    person.age = age;
    person.job = job;
    person.sayHi = function(){
        console.log('Hello,everyBody');
  };
  return person;
}
var p1 = createPerson('monster',23,'cleaner')
複製程式碼

自定義建構函式(推薦)

function Person(name,age,job) {
    this.name = name;       //this指向當前物件,this.name動態的為物件新增name 屬性,並且使name的值等於傳過來引數的值
    //注意形參的名字要和後面的name一樣;比如傳過來的形參是a,那麼this.name = a
    this.age = age;
    this.job = job;
    this.sayHi = function(){
  	console.log('Hello,everyBody');
  }
}
var p1 = new Person('monster',23,'cleaner')
複製程式碼
注意:
1. 建構函式用於建立一類物件,首字母要大寫。

還記得狗狗這一類吧,建構函式相當於建立了“狗”類,然後隨便你要什麼狗,
哈士奇,泰迪,直接new Dog('二哈','白色') 建立狗這個物件。。
2. 建構函式要和new一起使用才有意義。
複製程式碼
new在執行時會做四件事情:

new會在記憶體中建立一個新的空物件
new 會讓this指向這個新的物件
執行建構函式  目的:給這個新物件加屬性和方法
new會返回這個新物件
複製程式碼

this

this的指向問題還是挺讓人頭疼的,實驗結果如下

1.函式中的this  -----> 指向window
 function fn() {
     console.log(this);
 }
 fn()
 
2.方法中的this  -----> 指向方法所屬的物件
var obj = {
    name : 'monster',  //注意逗號結尾
    fn : function() {
        console.log(this)
    }
}
obj.fn()

3.建構函式中的this  ----->   指向建構函式建立的物件
function Fn() {
this.name = 'monster'
    console.log(this)
}
var o = new Fn()  //呼叫建構函式
如果通過 Fn() 呼叫, 結果是指向window,以為是呼叫函式
複製程式碼
總結:
1. 函式在定義的時候this是不確定的,只有在呼叫的時候才可以確定
2. 一般函式直接執行,內部this指向全域性window
3. 函式作為一個物件的方法,被該物件所呼叫,那麼this指向的是該物件
4. 建構函式中的this其實是一個隱式物件,類似一個初始化的模型,所有方法和屬性都掛載到了這個隱式物件身上,後續通過new關鍵字來呼叫,從而實現例項化
複製程式碼

遍歷和刪除物件屬性

遍歷

for in 可以遍歷物件的屬性成員

var obj = {
  name: 'zs',
  age: 18,
  sex: true,
  sayHi: function () {
    console.log(this.name + '你好');
  }
  }
  for (var key in obj)  //key 是物件的屬性成員
  { 
    console.log(key + '---' + obj[key]) ;
  }
  //答應物件的屬性和對應的值
複製程式碼
可以通過迴圈的方式動態給物件增加屬性

var o = {};
for (var i = 0; i < 10; i++) {
    o[a + 'i'] = i * 2;
}
複製程式碼

刪除

通過delete刪除


function Fun() {
    this.name = 'monster'
}
var obj = new Fun()
console.log(obj.name); // monster
delete obj.name
console.log(obj.name); // undefined


複製程式碼

總結完這些不知不覺已經快深夜2點了~~
如果對您有幫助,就麻煩點個贊吧,歡迎交流

相關文章