1. 程式人生 > 其它 >JS筆記合集之物件

JS筆記合集之物件

物件

物件基本使用

物件是JS中的一種複合資料型別,它相當於一個容器,在物件中可以儲存各種不同型別的資料

而基本資料型別(原始值)只能儲存一些簡單的資料,如:

語法:
	原始建立物件:
		let obj = new Object()
    向物件中新增屬性
	    物件.屬性名 = 屬性值
	obj.name = 'taotao'
	讀取物件中的屬性
    	物件.屬性名
	obj.name
	如果讀取的是一個物件中沒有的屬性,不會報錯,會返回 undefined
	修改屬性:
    	物件.屬性名 = 新值
	刪除屬性:
    	delete obj.name

物件中的屬性

屬性名

​ 通常屬性名就是一個字串,所以屬性名可以是任何值,沒有什麼特殊要求

​ 如果不能直接使用,需要用[] 的形式來設定

屬性值

		物件的屬性值可以是任意的資料型別,也可以是一個物件
	obj["@12sincjis"] = "taotao"// 不建議

屬性的兩種寫法:
		obj.name = 'taotao'
		obj['name'] = 'taotao'

in 運算子

  • 用來檢查物件中是否含有某個屬性

  • 語法 屬性名 in obj

  • 如果有返回true,沒有返回false

  console.log("name" in obj)

物件字面量

物件字面量

​ 可以直接使用{}來建立物件

​ 使用{}所建立的物件,可以直接向物件中新增屬性

​ 語法: {

​ 屬性名:屬性值,

​ }

 let mySymbol = Symbol() 
	let obj2 = {
            name:"孫悟空", 
            age:18,
            ["gender"]:"男",
            [mySymbol]:"特殊的屬性",
            hello:{
                a:1,
                b:true
            }
        }

列舉屬性

列舉屬性

​ 指將物件中的所有屬性全部獲取

​ 我們這裡可以利用 for - in語句

- 語法:    `for(let propName in 物件){        語句...    }`
-  for-in的迴圈體會執行多次,有幾個屬性就會執行幾次,    每次執行時,都會將一個屬性名賦值給我們所定義的變數
- 注意:並不是所有的屬性都可以列舉,比如 使用符號新增的屬性
 for(let propName in obj){
            console.log(propName, obj[propName])  //拿到所有的屬性名和屬性值
        }

可變型別

- 原始值都屬於不可變型別,一旦建立就無法修改
- 在記憶體中不會建立重複的原始值
 		let a = 10 
        let b = 10
        a = 12 // 當我們為一個變數重新賦值時,絕對不會影響其他變數
  • 物件屬於可變型別-
  • 物件建立完成後,可以任意的新增刪除修改物件中的屬性
  • 注意:
    • 當對兩個物件進行相等或全等比較時,比較的是物件的記憶體地址
    • 如果有兩個變數同時指向一個物件, 通過一個變數修改物件時,對另外一個變數也會產生影響
		let obj = {
            name:"孫悟空", 
            age:18, 
        }
        let obj2 = obj   // 當修改一個物件時,所有指向該物件的變數都會收到影響
        

更改變數和物件

修改物件

  • 修改物件時,如果有其他變數指向該物件 則所有指向該物件的變數都會受到影響

    修改變數

  • 修改變數時,只會影響當前的變數

  • 在使用變數儲存物件時,很容易因為改變變數指向的物件,提高程式碼的複雜度,所以通常情況下,宣告儲存物件的變數時會使用const

注意: const禁止變數被重新賦值,對物件的修改沒有任何影響

物件中的方法

方法(method)

  • 當一個物件的屬性指向一個函式,那麼我們就稱這個函式是該物件的方法
  • 呼叫函式就稱為呼叫物件的方法
 // 函式也可以成為一個物件的屬性
        obj.sayHello = function(){
            alert("hello")
        }
----------在物件中簡寫
	let obj = {
            name:"孫悟空", 
            age:18, 
       		sayHello(){
           		  alert("hello")
        	}
        }
		

函式

函式的基本概念和使用

函式(Function)

  • 函式也是一個物件

  • 它具有其他物件所有的功能

  • 函式中可以儲存程式碼,且可以在需要時呼叫這些程式碼

  • 簡單的來說,就是可以複用程式碼,提高開發效率

    語法: function 函式名(){ 語句... }

    呼叫函式

    • 呼叫函式就是執行函式中儲存的程式碼
    • 語法: 函式物件()
    • 使用typeof檢查函式物件時會返回function
//建立一個物件 
	function fn(){
       console.log("你好!")
    }
	fn()  //呼叫
   console.log(typeof fn)   // Function

函式的建立方式

三種方式:

函式的定義方式

1.函式宣告 function 函式名(){ 語句... }

2.函式表示式 const 變數 = function(){ 語句... }

3.箭頭函式 () => { 語句... }

 	 function fn(){
            console.log("函式宣告所定義的函式~")
        }

        const fn2 = function(){
            console.log("函式表示式")
        }

        const fn3 = () => {
            console.log("箭頭函式")
        }

        const fn4 = () => console.log("箭頭函式")

函式的引數

形式引數(形參)

  • 在定義函式時,可以在函式中指定數量不等的形式引數(形參) -

  • 在函式中定義形參,就相當於在函式內部聲明瞭對應的變數但是沒有賦值

    實際引數(實參)

  • 在呼叫函式時,可以在函式的()傳遞數量不等的實參

    • 實參會賦值給其對應的形參
      • 引數:
      • 1.如果實參和形引數量相同,則對應的實參賦值給對應的形參
      • 2.如果實參多餘形參,則多餘的實參不會使用
      • 3.如果形參多餘實參,則多餘的形參為undefined
        • 引數的型別
        • JS中不會檢查引數的型別,可以傳遞任何型別的值作為引數
	 function sum(a, b){
            console.log(a + b)
        }
	sum(1,2)

箭頭函式的引數

	 const fn = (a, b) => {
            console.log("a =", a);
            console.log("b =", b);
        }
     fn(1,2)

當箭頭函式中只有一個引數時,可以省略()

  		const fn2 = a => {
            console.log("a =", a);
        }

​ 我們在定義引數的時候可以指定預設值

 const fn3 = (a=10, b=20, c=30) => {
            console.log("a =", a);
            console.log("b =", b);
            console.log("c =", c);
        }

        fn3(1, 2)
//c的值沒有傳遞,所以取到預設值30

物件作為引數

let obj = {name:'taotao'}
function fn(obj){
    
}
//傳遞實參時,傳遞並不是變數本身,而是變數中儲存的值
fn(obj)

// 函式每次呼叫,都會重新建立預設值
        function fn2(a = {name:"沙和尚"}){
            console.log("a =", a)
            a.name = "唐僧"
            console.log("a =", a)
        }

        fn2() // 沙和尚 唐僧
        fn2() // 沙和尚 唐僧 or 唐僧 唐僧

函式作為引數

​ 在JS中,函式也是一個物件(一等函式)

​ 別的物件能做的事情,函式也可以

 	function fn(a){
            console.log("a =", a)
     			//函式中呼叫另一個函式
           a()  //執行的就是箭頭函式
        }
//呼叫的時候傳遞的就是一個箭頭函式,傳遞過去的就是a這個函式
	fn(()=>console.log("我是箭頭函式"))

函式的返回值

​ 我們一般都是返回,而不是在控制檯中列印

function sum(a, b){
    return a + b
}
sum(1, 2)  // 返回值就是函式的執行結果
  • ​ 在函式中,可以通過return關鍵字來指定函式的返回值

  • 返回值就是函式的執行結果,函式呼叫完畢返回值便會作為結果返回

  • return一執行函式立即結束, return 之後的所有語句都不會執行

  • 任何值都可以作為返回值使用(包括物件和函式之類)

  • 如果return後不跟任何值,則相當於返回undefined

  • 如果不寫return,那麼函式的返回值依然是undefined

箭頭函式的返回值

  • ​ 箭頭函式的返回值可以直接寫在箭頭後
  • 如果直接在箭頭後設置物件字面量為返回值時,物件字面量必須使用()括起來
const sum = (a, b) => a + b   //如果只要一條執行語句的話,可以省略 return
const fn = name => ({name:"孫悟空"})  //如果只要一個引數,可以省略括號,物件字面量必須使用()括起來

作用域(scope)

  • 作用域指的是一個變數的可見區域

  • 作用域有兩種:

    • 全域性作用域

      • 全域性作用域在網頁執行時建立,在網頁關閉時銷燬
      • 所有直接編寫到script標籤中的程式碼都位於全域性作用域中
      • 全域性作用域中的變數時全域性變數,可以在任意地方訪問
    • 區域性作用域

      • 塊級作用域

        • 塊級作用域是一種區域性作用域

        • 塊級作用域在程式碼塊執行時建立,程式碼執行完畢它就銷燬了

        • 在塊級作用域中宣告的變數是區域性變數,只能在塊內部訪問,外部無法訪問

        •   		{
                          let b = "變數b"
          
                          {
                              {
                                  //這裡根據作用域鏈的查詢機制,一層一層往上查詢,是可以找到變數b的
                                  console.log(b) 
                              }
                          }
                      }
          
                      {
                          //這裡是訪問不到變數b的,會報錯
                          console.log(b)  
                      }
          
      • 函式作用域

        • 函式作用域也是一種區域性作用域

        • 函式作用域在函式呼叫時產生,呼叫結束後銷燬

        • 函式每次呼叫都會產生一個全新的函式作用域

        • 在函式中定義的變數是區域性變數,只能在函式內部訪問,外部無法訪問

        • 	function fn(){
                      let a = "fn中的變數a"
            
                      console.log(a)
                  }
            
                  fn()
            		//這裡是無法訪問到變數a的,會報   a is not defined
                  console.log(a)
          

作用域鏈

​ 當我們使用一個變數時,

​ JS直譯器會優先在當前作用域中尋找變數,如果找到了則直接使用

​ 如果沒找到,則去上一層作用域中尋找,找到了則使用

​ 如果沒找到,則繼續去上一層尋找,以此類推

​ 如果一直到全域性作用域都沒找到,則報錯 x is not defined

	let b = 33

        function fn(){
            let b = 44

            function f1(){
                let b = 55
                console.log(b)
            }

            f1()
            
        }

        fn()

Window物件

window物件

  • ​ 在瀏覽器中,瀏覽器為我們提供一個window物件,可以直接訪問

  • window物件代表瀏覽器視窗,通過該物件可以對六拉尼去視窗進行各種操作

    • 除此之外window物件還負責儲存JS中的內建物件和瀏覽器的宿主物件
  • window物件的屬性可以通過window物件訪問,也可以直接訪問

  • 函式就可以認為是window物件的方法

    alert(window)
          window.alert(123)
       			window.console.log("哈哈")
    

    var用來宣告變數,作用和let相同,但是var不具有塊作用域

    • 在全域性中使用var宣告的變數,都會作為window物件的屬性儲存
    • 使用function宣告的函式,都會作為window的方法儲存
    • 使用let宣告的變數不會儲存在window物件中,而存在一個祕密的小地方(無法訪問)
    • var雖然沒有塊作用域,但有函式作用域
    • 在區域性作用域中,如果沒有使用var或let宣告變數,則變數會自動成為window物件的屬性 也就是全域性變數

變數提升

變數的提升

  • 使用var宣告的變數,它會在所有程式碼執行前被宣告

所以我們可以在變數宣告前就訪問變數函式的提升

  • 使用函式宣告建立的函式,會在其他程式碼執行前被建立

    所以我們可以在函式宣告前呼叫函式let宣告的變數實際也會提升,但是在賦值之前直譯器禁止對該變數的訪問

作用域小練習:
	   var a = 1
        function fn(){
            a = 2
            console.log(a) // 2
        }
        fn()
        console.log(a) // 2 
---------
            // 變數和函式的提升同樣適用於函式作用域
     var a = 1
        function fn(){
            console.log(a) //undefined
            var a = 2
            console.log(a) // 2
        }
        fn()
        console.log(a) // 1 
-----------------
             // 定義形參就相當於在函式中聲明瞭對應的變數,但是沒有賦值
       var a = 1
        function fn(a){
            console.log(a) //undefined
            a = 2
            console.log(a) // 2
        }
        fn()
        console.log(a) // 1    
-------------------
      var a = 1
        function fn(a){
            console.log(a) //10
            a = 2
            console.log(a) // 2
        }
        fn(10)
        console.log(a) // 1
--------------------
 	var a = 1
        function fn(a){
            console.log(a) //1
            a = 2
            console.log(a) // 2
        }
        fn(a)
        console.log(a) // 1 

debug

debug是進行斷點除錯的,如果出現bug了,我們可以在控制檯裡面卡斷點

打完斷電一定要重新整理,這樣才可以進入斷點內

立即執行函式

​ 在開發中應該儘量減少直接在全域性作用域中編寫程式碼!

​ 所以我們的程式碼要儘量編寫的區域性作用域

​ 如果使用let宣告的變數,可以使用{}來建立塊作用域

立即執行函式(IIFE)

  • 立即是一個匿名的函式,並它只會呼叫一次
  • 可以利用IIFE來建立一個一次性的函式作用域,避免變數衝突的問題
		(function(){
            let a = 10
            console.log(111)
        }())

this指向問題

this

  • 函式在執行時,JS解析器每次都會傳遞進一個隱含的引數

  • 這個引數就叫做 this

  • this會指向一個物件

  • this所指向的物件會根據函式呼叫方式的不同而不同

  • 1.以函式形式呼叫時,this指向的是window

  • 2.以方法的形式呼叫時,this指向的是呼叫方法的物件

  • ......

  • 通過this可以在方法中引用呼叫方法的物件

後面出一個專門this指向的問題

箭頭函式的this

箭頭函式

([引數]) => 返回值

例子:

  1. 無參箭頭函式:() => 返回值
  2. 一個引數的:a => 返回值
  3. 多個引數的:(a, b) => 返回值
  4. 只有一個語句的函式:() => 返回值
  5. 只返回一個物件的函式:() => ({...})
  6. 有多行語句的函式:() => { .... return 返回值 }
  7. 箭頭函式沒有自己的this,它的this有外層作用域決定
  8. 箭頭函式的this和它的呼叫方式無關
    const fn2 = () => {
                console.log("fn2 -->", this) // 總是window
            }

嚴格模式

​ JS執行程式碼的模式有兩種:

  • 正常模式
  • 預設情況下程式碼都執行在正常模式中,
  • 在正常模式,語法檢查不嚴格
  • 能不報錯就不報錯
  • 這種處理方式導致程式碼的執行效能較差
  • 嚴格模式
    • 在嚴格模式下,語法檢查變得嚴格
    • 1.禁止一些語法
    • 2.更容易報錯
    • 3.提升了效能
  • 在開發中,我們儘量使用嚴格模式,這樣可以將一些隱藏的問題給消除,同時也能提高效能
 	"use strict" // 全域性的嚴格模式
 	function fn(){
            "use strict" // 函式的嚴格的模式
        }