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
箭頭函式
:
([引數]) => 返回值
例子:
- 無參箭頭函式:
() => 返回值
- 一個引數的:
a => 返回值
- 多個引數的:
(a, b) => 返回值
- 只有一個語句的函式:
() => 返回值
- 只返回一個物件的函式:
() => ({...})
- 有多行語句的函式:
() => { .... return 返回值 }
- 箭頭函式
沒有自己的this
,它的this有外層作用域決定
箭頭函式的this和它的呼叫方式無關
const fn2 = () => {
console.log("fn2 -->", this) // 總是window
}
嚴格模式
JS執行程式碼的模式有兩種:
- 正常模式
- 預設情況下程式碼都執行在正常模式中,
- 在正常模式,語法檢查不嚴格
- 能不報錯就不報錯
- 這種處理方式導致程式碼的執行效能較差
- 嚴格模式
- 在嚴格模式下,語法檢查變得嚴格
- 1.禁止一些語法
- 2.更容易報錯
- 3.提升了效能
- 在開發中,我們儘量使用嚴格模式,這樣可以將一些隱藏的問題給消除,同時也能提高效能
"use strict" // 全域性的嚴格模式
function fn(){
"use strict" // 函式的嚴格的模式
}