JS內建物件,函式與作用域

weixin_34037977發表於2017-05-31

1.JavaScript基於物件的語言

JavaScript和PHP不一樣的地方在於:

  • PHP是面嚮物件語言,先有類再例項化物件;
  • JavaScript是基於物件的語言,也就是說JavaScript是由很多內建的物件組成的程式語言;


    4679780-eb557e3e1597e706.png
    JavaScript的主要內建物件

1.1陣列物件

物件主要是由屬性、方法組成的,所以學習陣列物件就是學習陣列物件提供的屬性和方法;

  • length屬性,獲得陣列元素的個數
4679780-c4cf68609b270f8f.png
length屬性獲取陣列元素的個數
  • concat:連線陣列生成新的陣列
4679780-385a1c668114a1f5.png
concat屬性連線陣列生成新的陣列
  • join,使用指定的分隔符將陣列連線成字串
4679780-6271825b25cddf94.png
join使用特定的分隔符將陣列連線成字串
  • push、pop:分別表示向陣列末尾新增元素、刪除末尾的元素
4679780-d45493d7bbbe1ee0.png
分別兩陣列末尾新增元素,刪除末尾元素
  • shift、unshift分別表示刪除陣列第一個元素、向陣列開頭新增一個元素
4679780-0d68e1320398fa0f.png
新增陣列第一個元素,刪除陣列第一個元素
  • reverse,顛倒陣列順序
4679780-47b073865e36494b.png
顛倒陣列元素的順序
  • slice(),擷取陣列元素,並將擷取的部分返回
    引數1:開始的索引位置
    引數2:結束的索引


    4679780-d8ad7acde08cf316.png
    擷取字串
  • splice() 刪除陣列元素,這個方法在執行時返回的是刪除的陣列元素
    引數1:開始的索引位置
    引數2:刪除的元素個數
    引數3:可選的,如果有引數3,表示使用引數3代替刪除的那些元素


    4679780-3170531d454fd6ec.png
    splice方法比slice方法要強大一些
  • toString(), 將陣列轉換為字串,該結果的返回值是修改後的字串
4679780-9a9b1e5aeec787f0.png
陣列轉換為字串,但是方法執行後要接收一下

1.2字串物件

  • indexOf(),獲得某個字元在字串整體中第一次出現的索引
  • lastIndexOf(),獲得某個字元在字串整體中最後一次出現的索引
4679780-d0b741556426438b.png
查詢某個字元在字串中首次,末次出現的索引位置
  • split(),根據指定的分隔符,將字串拆分成陣列
    引數1:分隔符號
    引數2:限制返回的結果數量
4679780-ec1130ad92165d83.png
split是經常使用的方法
  • replace,字串替換
    引數1:正規表示式
    引數2:替換的結果
4679780-aaf3d94c44d51bc7.png
字串替換
  • match()方法,用來根據正規表示式進行篩選
4679780-1a6a248b16ee5e7f.png
注意match方法是比較常用的利用正規表示式來匹配字串的方法
  • charAt(),用來獲得在指定索引位置的字元是什麼?
    引數:索引位置
4679780-abb347b597f41383.png
查詢在指定索引位置的字元是什麼
  • slice,字串擷取
    引數1:開始的索引位置
    引數2:結束的索引位置
4679780-12d05c413a9c20c6.png
不包括包含位置
  • substr()
    引數1:開始的索引位置,如果正數從0開始;如果是負數,從後面向前面數
    引數2:擷取的長度
4679780-b87f42f3d94cc3e8.png
要注意負數的情況
  • toLowerCase(),將字串轉換成小寫
    toUpperCase(),將字串轉換成大寫
4679780-95f15d0fb4e34e1c.png
將字串轉換為大寫或者小寫

1.3數學物件

JavaScript給我們提供的用來進行數學計算的物件,Math

  • Math.abs(),計算一個數值的絕對值,例如 -9的絕對值就是:9


    4679780-c9277c57a9f4335b.png
    計算一個數值的絕對值
  • Math.ceil(),向上取整,進一取整


    4679780-a91ca3b9f9702d9c.png
    要注意負數的情況
  • Math.floor(),向下取整

4679780-812edd2c425a95b7.png
數字向下取整
  • Math.round(),四捨五入取整
4679780-ec6289deac21491b.png
四捨五入
  • max(),獲得最大值
    min(),獲得最小值
4679780-c5c50de4f6c26fd2.png
取最大最小值
  • Math.pow(x,y)計算x的y次方
4679780-2748d7fbbe7c20b2.png
計算某數的次方
  • Math.sqrt(),返回數值的平方根
4679780-c1c044f3045fbf51.png
返回數值的平方根

Math.random(),返回0-1之間的小數,這是js中取隨機數的一種方法

1.4日期物件

說明:日期物件是JavaScript封裝的用來操作日期、時間的物件
通過new Date()獲得日期物件

  • getFullYear(),獲得年份
    getMonth(),獲得當前的月份
    getDate()獲得當前的日期
    getHours()獲得當前的時間
    getMinutes()獲得當前的分鐘
    getSeconds()獲得當前的秒數
4679780-f53a6bbc7cc5f012.png
日期時間
  • getDay(),獲得當前是星期幾?
4679780-37280f3b4c5bc0ea.png
獲取當前是星期幾
  • getMiliseconds()獲得當前時間的毫秒部分:1000毫秒==1秒
4679780-1514bddbd7e2a7b8.png
毫秒部分

\

  • getTime(),獲得當前的時間戳(單位毫秒)php時間戳的單位是(秒)
  • toLocaleString(),將日期物件轉換成本地時間格式
4679780-38e3ba809f11e86e.png
  • 設定日期:
    setFullYear(),設定年份
    setMonth(),設定月份
    setDate(),設定日期
    獲得上個月1號是星期幾?
4679780-858b2bb93a3ddd8a.png
image.png

getDay()返回的是0-6的數字,分別代表了0為星期日,6為星期六;

1.5正規表示式物件

這個在正規表示式,我有做詳細的論述

1.6DOM物件

這個在DOM操作這章我有做詳細的論述

1,7BOM物件

BOM,Browser Object Model,瀏覽器物件模型,獨立於內容之外的,和瀏覽器進行互動的物件(前進、後退、位址列、瀏覽器本身一些資訊等)
BOM這個瀏覽器物件模型給我提供瞭如下子物件和瀏覽器進行互動:

  • location物件,操作瀏覽器位址列
4679780-935a0cd9ae4e0ff5.png
location物件操作瀏覽器的地址
  • history物件,操作瀏覽器歷史記錄(前進、後退、重新整理)
    history.go(-1),後退1步
    history.go(-2),表示後退2步
    ....
    history.go(1),前進1步
    history.go(0):重新整理頁面
    ....
    history.forward():前進一步
    history.back():後退1步

  • screen物件,獲得螢幕解析度

4679780-77f2fd27022d4b5d.png
要注意可用寬高和實際寬高的區別
  • navigator物件,獲得瀏覽器本身的資訊
    appName: 返回瀏覽器核心名稱
    appVersion: 返回瀏覽器和平臺的版本資訊
    platform: 返回執行瀏覽器的作業系統平臺
    userAgent: 返回由客戶機傳送伺服器的 user-agent 頭部的值
4679780-3b9d222071358bf9.png
這部分內容瞭解即可,不必過於深入

1.8 Window物件

window,指的是瀏覽器視窗,也是javascript的一個頂層物件,該物件包括DOM
、BOM,也就是說:DOM物件、BOM物件都是window的子物件

4679780-b221d4a748ce5f2d.png
window物件是js的頂層物件

除了DOM、BOM之外,window物件還提供了一些方法供我們使用:

  • alert():彈出警告框

  • confirm(),彈出一個確認框
    引數:彈出框顯示的內容
    返回布林值,點選確定返回true,點選取消返回false

4679780-ec73cf6f24adde47.png

如果點選確定,則返回true,如果點選取消則返回false

  • prompt(),彈出一個輸入框
    //引數1:在輸入框提示的資訊
    //引數2:預設值
    //返回值:點選確定獲得輸入框的內容;點選取消返回null
4679780-30c959551d2cbbec.png
彈出一個輸入框
  • setInterval,設定計時器(定時炸彈),每間隔指定的時間就執行一次
  • clearInterval,清除計時器
    //開啟一個計時器,每間隔1秒執行一次
    //引數1:執行的函式體
    //引數2:間隔的時間,單位是毫秒
    //返回值:id,將來刪除這個計時器的標記
  • setTimeout,設定延遲執行,延遲指定的時間執行一次
  • clearTimeout,清除延遲執行

<h1>複習部分</h1>
<h1>1.什麼是變數的宣告前置?什麼是函式的宣告前置?</h1>
所謂變數提升是指javaScript引擎的一種工作方式,先解析程式碼,獲取所有宣告的變數,之後再一行一行的執行,因此我們在js中先宣告變數,再給變數賦值,其執行機制是先把變數的宣告語句提升到程式碼的頭部,相當於在程式碼的預執行階段,變數就已經在頭部執行了,並賦值為undefined;
而函式宣告前置,則是在函式預執行階段,將函式宣告語句提到程式碼頭部執行,那麼該函式實際在程式碼正式執行之前就已經宣告過了,因此在js中,呼叫函式語句可以寫在函式宣告語句的前面.

<h1>2.函式宣告和函式表示式有什麼區別?</h1>
<h3>首先明白怎麼定義函式?</h3>
定義函式的方法有三種:

  • 1.函式宣告(Function Declaration)
  • 2.函式表示式(Function Expression)
    1. new function 建構函式,這種方式不推薦使用;

函式宣告語法格式如下:
function functionName(){ statement; } printName();

函式宣告的重要特徵之一是<b>函式宣告提升</b>,意思是執行程式碼之前會讀取函式宣告,這也就意味著函式宣告可以放在呼叫它的語句後面,如下:
sayHi(); function sayHi(){ alert("Hi"); }
結果是返回彈窗Hi.

函式表示式語法格式如下:
var printName = function(){ console.log('Byron'); };

函式表示式的形式看起來似乎是一個常規的變數賦值語句,即將函式作為一個值賦給變數,同樣的也能夠將函式作為其他函式的值返回.

<h3>那麼函式表示式與函式宣告有什麼區別了?</h3>

  • 函式表示式可以沒有函式名,這種情況建立的函式稱之為匿名函式;函式宣告必須要有函式名,我們試試看
4679780-188d58bd3131e496.png
4679780-63d36c30b88e6aaf.png

宣告函式時,不設定函式名會提示語法錯誤;

  • 函式表示式與函式宣告的最重要區別就在於函式宣告會提升
    因為函式宣告會提升,在執行程式碼之前會讀取函式宣告,想當於在程式碼執行之前,函式宣告已經執行過了,而函式表示式則是程式碼執行到函式表示式之後再進行執行.

<h1>3.arguments 是什麼?</h1>
在函式內部可以使用arguments物件獲取到該函式的所有傳入引數:

<h1>4.函式的"過載"怎樣實現?</h1>
在JavaScript中沒有函式過載的概念,函式通過名字確定唯一性,引數不同也被認為是相同的函式,後面的覆蓋前面的.
可以在函式體針對不同的引數呼叫執行相應的邏輯。如下所示:
`function printPeopleInfo(name, age, sex){
if(name){
console.log(name);
}

if(age){
    console.log(age);
}

if(sex){
    console.log(sex);
}

}
printPeopleInfo('Byron', 26);
printPeopleInfo('Byron', 26, 'male');`

<h1>5.立即執行函式表示式是什麼?有什麼作用</h1>
立即執行函式表示式就是(function(){})()
使用立即執行函式表示式的作用是隔離變數,防止全域性變數被汙染;

<h1>6.求n!,用遞迴來實現</h1>

4679780-747bafa2a21e77c3.png
4679780-a582425e3f1a46e4.png

<h1>7.以下程式碼輸出什麼?</h1>

4679780-19db17c3d150a0ff.png

輸出結果應該是:
//name:飢人谷; age:2; sex:男;name:valley;
//name:小谷; age:3; sex: undefined;name:valley;
//name:男;age: undefined; sex: undefined; name: valley;

<h1>8.寫一個函式,返回引數的平方和?</h1>


4679780-dee457e7cc4da0df.png

平方和函式如下:

4679780-5f91fc280c747991.png

<h1>9. 如下程式碼的輸出?為什麼?</h1>

4679780-9224c1155dba00d2.png
  • 應該是輸出undefined 以及報錯,原因在於:變數提升,a由於提到程式碼頭部,被賦值undefined,因此輸出undefined,而b未定義,因此會報錯;
4679780-3ff1c66bc7639413.png

<h1>10. 如下程式碼的輸出?為什麼</h1>

4679780-459ea4579b829dff.png
  • 由於函式宣告提升,而函式表示式不會提升,因此在程式碼預執行階段,函式宣告已經提升至程式碼頭部,接下來執行階段,sayName('world')輸出helloworld,而到了執行sayAge(10)階段,由於函式表示式相當於還未宣告,因此會報錯,這個函式尚不存在!
4679780-9fdd30163dce3457.png

<h1>11. 如下程式碼輸出什麼? 寫出作用域鏈查詢過程虛擬碼</h1>

4679780-9d0c6c9ca555973a.png
1.全域性作用域:
globalContext = {
    AO: {
        x: 10;
        foo: function;
        bar: function;
    }
    Scope: null;
}
//宣告foo時,得到scope屬性
foo.[[scope]] = globalContext.AO;
//宣告bar時,得到scope屬性
bar[[scope]] = globalContext.AO;

2.當呼叫bar()時,進入bar的執行上下文
barContext = {
    AO:{
        x: 30;
    }
    Scope: bar.[[scope]]// bar[[scope]] = globalContext.AO
}

3.呼叫foo(),先從bar執行上下文的活動變數(AO)中找,找不到再從bar.[[scope]]中找,找到後進行呼叫
4.呼叫foo(),進入foo的執行上下文
fooContext{
    AO{
        null
    }
    Scope: foo.[[scope]]//foo.[[scope]]=globalContext.AO;
}
5.在globaContext.AO中,x:10;因此呼叫foo()輸出為10;
6.整體呼叫bar[],輸出結果為10;

4679780-11542785d888a8a2.png

結果於預期一致,輸出為10;

<h1>12. 如下程式碼輸出什麼? 寫出作用域鏈查詢過程虛擬碼</h1>

4679780-f19ca6fa1e2d9746.png
1.全域性作用域
globalContext{
    AO{
        x:10;
        bar: function;
    }
    Scope: null
}
//宣告函式bar得到Scope屬性
bar[[scope]] = globalContext.AO;
2.執行bar(),進入bar的執行上下文
bar.Context{
    AO{
        x: 30;
        foo : function;
    }
    Scope: bar[[scope]]//bar[[scope]]=globalContext.AO
        }
//宣告函式foo得到其Scope屬性
foo[[scope]] = bar.context.AO;

3.執行bar()時,呼叫foo(),這時進入foo的執行上下文
foo.Context{
    AO{
        null;
    }
    Scope: foo.[[scope]];//foo.[[scope]]=bar.context.AO
}
4.執行console.log(x),x從當前foo.Context.AO中查詢,無果,從foo.[[scope]]中查詢,實質上就是從bar.Context.AO中查詢,查到x=30,因此輸出結果應該為30;

4679780-1822e7858f058cd8.png

如同預期輸出結果為30;

<h1>13. 以下程式碼輸出什麼? 寫出作用域鏈的查詢過程虛擬碼</h1>

4679780-9c82b1a713d88663.png
  1.全域性作用域
globalContext{
    AO{
        x :10;
        bar : function;
    }
    Scope: null;
}
//宣告bar函式時,bar函式得到Scope屬性
bar.[[scope]] =  globalContext.AO;

2.執行bar(),進入bar的執行上下文
bar.Context{
    AO{
        x: 30;
        立即執行函式(匿名函式): function;
    }
    Scope: bar.[[scope]] //bar.Context=globalCotext.AO;
}
宣告立即函式時,立即執行函式得到屬性Scope
function.[[scope]] = bar.Context.AO;

3.呼叫立即執行函式,進入其執行上下文
function.Context{
    AO{
        null;
    }
    Scope: function.[[scope]];
}

4.執行console.log(x),x從當前執行上下文中查詢,先查function.Context.AO,無果,之後從function.[[scope]]中查詢,function.[[scope]]=bar.Context.AO, 從中查詢查x=30;
    輸出 30;       

<h1>14. 以下程式碼輸出什麼? 寫出作用域鏈查詢過程虛擬碼</h1>

4679780-4b1772b8a926d320.png
 1.全域性作用域
globalContext{
    AO{
        a: 1;
        fn : function;
        fn3 : function;
    }
    Scope: null;
}
//宣告函式fn時,得到其Scope屬性 
fn.[[scope]]  = globalContext.AO;
//宣告函式fn3時,得到其Scope屬性
fn3.[[scope]] = globalContext.AO;

2.呼叫fn(),進入fn的執行上下文
fnContext{
    AO{
        a:5;
        a:6;
        fn2: function;
    }
    Scope: fn.[[scope]] //fn.[[scope]] = globalContext.AO 
       }
//宣告fn2,得到其屬性Scope
fn2.[[scope]] = fnContext.AO;

3.執行第一個console.log(a),輸出為undefined;

4.賦值操作,a=5;

5.執行第二個console.log(a),輸出5;

6.a++,a =6;

7.呼叫fn3(),進入fn3的執行上下文
fn3Context{
    AO{
        null
    }
    Scope: fn3.[[scope]];//fn3.[[scope]]=globalContext.AO;
}

8.執行fn3內部console.log(a),a搜尋當前執行上下文,從fn3,[[scope]]中搜尋,a=1;輸出1;之後執行賦值操作,a=200;呼叫fn3完畢

9.呼叫fn2(),進入fn2的執行上下文
fn2Context{
    AO{
        null
    }
    Scope: fn2.[[scope]]//fn2.[[scope]] = fnContext.AO;
}

10.執行fn2內部的console.log(a),a從當前執行上下文中搜尋,從fn2.[[scope]]中搜尋得a=6,輸出5;之後賦值操作,a=20;呼叫fn2結束

11.執行console.log(a),輸出20;呼叫fn()結束;

12.執行console.log(a),此時全域性變數a為200;

總的輸出: undefined,5,1,6,20,200;

相關文章