1. 程式人生 > >JS第一周學習筆記整理

JS第一周學習筆記整理

業務邏輯 註釋 如何判斷 email 聲明 變量賦值 nts 自帶 小括號

目錄

  • JS正式課第一周筆記整理

JS正式課第一周筆記整理

  • webstorm : 代碼編輯器
  • 瀏覽器: 代碼解析器;
  • Git : 是一個工具;用於團隊協作開發項目管理代碼的工具;在工作中用git、svn
  • svn : 集中式;
  • 集中式:需要一個中央服務器;每次開發前需要從中央服務器把最新的代碼拉取下來,然後進行開發;並且需要網絡;
  • git : 分布式;
  • 分布式:每個人的電腦都是一個中央服務器;不需要網絡也可以進行提交代碼;

DOS命令

  • 1.按著shift右鍵,在此處打開powerShell
  • 2.找到相應的文件夾,直接輸入cmd,按回車;
  • window+r : 輸入cmd

    切換磁盤路徑
    • cd + 文件夾名字: 打開相應的路徑
    • cd ../ : 回到上一級
    • cd / : 回到跟路徑;
    • mkdir + 文件名字 : 創建文件夾
    • cls : 清除所有的命令

    Git

    配置Git用戶名和密碼
  • git config --global user.email "郵箱"
  • git config --global user.name "用戶名"

Git的簡單命令
  • git init : 初始化一個git 倉庫(生產.git文件)
  • git add . : 把所有文件提交到暫存區
  • git add [文件名]:推送指定的文件到暫存區
  • git commit -m"註釋" : 把代碼提交到歷史區;(推送到歷史區之後Git會自動分配一個版本號xxxxxx
    ,根據版本號可以回到任何一次修改的位置
    )
  • git status:查看文件狀態;如果文件只存在本地,不在暫存區,那麽顏色是紅色,如果文件在暫存區還沒有提交到歷史區,那麽顏色是綠色
  • 本地代碼- ->暫存區- ->歷史區

    本地倉庫與遠程倉庫通信
  • git remote add origin(倉庫名) url地址:將本地倉庫與遠程倉庫建立連接
  • git remote -v:查看本地倉庫和遠程倉庫關聯狀態
  • git push origin(與建立連接時的倉庫名一樣) master(主分支名):將歷史區內容推送到遠程倉庫
  • git config --list:查看本地配置環境
  • 輸入用戶名和密碼

    推送過程(詳細步驟)
    本地操作
  • ① git init(初始化git倉庫)
  • ② git add .(將文件推送到暫存區)
  • ③ git status(查看文件狀態)
  • ④ git commit -m "註釋"(將代碼提交到歷史區,並添加註釋)

    遠程倉庫操作
  • git remote add origin(倉庫名) url地址
  • git remote -v
  • git push origin(倉庫名) master
    技術分享圖片

    推送復原過程

    技術分享圖片

    拉取克隆過程(詳細步驟)
  • git clone 倉庫地址url:這裏已經是一個git倉庫,並且已經和遠程建立和連接
  • git pull origin master:拉取遠程倉庫代碼
    技術分享圖片

GitHub

  • GitHib:是一個開源網站,可以供大家分享代碼 插件和框架
  • 把本地的代碼提交到遠程倉庫(GitHub)
  • 讓本地倉庫和遠程倉庫進行綁定

    作用域

    作用域:代碼執行的空間環境 ===棧內存

    瀏覽器的渲染機制:先形成一個DOM樹和CSS樹,最後兩個樹合成render樹

    全局作用域 : 當打開瀏覽器時,瀏覽器會形成一個全局的作用域,給當前代碼提供運行環境的;並且存儲基本數據類型值;
    • 存儲基本數據類型值
    • 基本數據類型存儲到棧內存中,全局作用域是最大的一個棧內存
    • window是全局中最大的一個對象,存儲了大量的內置屬性

    私有作用域:一個函數執行的時候就會形成一個私有作用域,函數執行完成(或關閉瀏覽器)就銷毀
    塊級作用域:ES6新增的,除了私有作用域和對象以外所有被一個{}包裹起來的,(三個判斷,三個循環)eval("({a:1})")、for 循環中用let ,會形成父作用域;每循環一次,都會形成一個子作用域;在子作用域中會把當前的i進行保存

全局變量:在全局作用域下定義的變量
  • 會給window新增一個鍵值對
  • 全局下定義的函數相當於給window新增鍵值對,屬性名是函數,屬性值是整個函數
私有變量:
  • 在函數體中被var 、function、const、let聲明
  • 函數的形參也是私有變量

    性能優化
//1-
function fn(){
//傳入任意參數求和
    var total = 0;
    var len = arguments.length;
//(var i = 0;i<arguments.lenth;i++)
    for(var i = 0;i<len;i++){
        var cur = arguments[i];
        if(!isNaN(cur)){
        //total += arguments[i];
        total += cur;
        }
    }
}
//2- in 方法用於檢測對象中是否有該屬性
function fn(){}
console.log(‘fn‘ in window);//true
//‘fn‘必須加引號,不叫引號就是這個變量對應的值

//3-
var a,b,fn = function(){
    var a = b = 10;
    //(var a = b = 10;-->var a = 10;b = 10;)
    //a變成了局部變量無法修改外部,b是全局變量,修改了外部
}
fn();
console.log(a,b);//undefined 10

變量提升

https://blog.csdn.net/zjy_android_blog/article/details/80863425

https://blog.csdn.net/longwenjunjie/article/details/48163293

變量提升的定義

變量提升:在作用域形成之後代碼執行之前,將所有帶var和function關鍵字的變量提前聲明或定義

JS可以在瀏覽器中農運行 是因為瀏覽器給JS提供了賴以生存的環境,這個環境就是作用域

  • var:只是提前聲明;默認值是undefined
  • function:既聲明又定義
  • debugger:打斷點

形成作用域-變量提升-代碼從上到下執行

變量提升的特殊情況
  • 不管條件是否成立,都要進行變量提升
  • 條件判斷中的函數,在條件判斷之前,帶var和帶function都只是聲明不定義
  • 當條件成立之後,第一件事就是給函數復制;
  • 條件不成立,判斷體就不執行,結合ES6的塊級作用域
  • 如果不帶var直接賦值就相當於給window直接添加了一個屬性 並且給它賦值
  • var就相當於子安全局作用域下增加了一個屬性,還給全局對象window增加了一個屬性
  • 註意: 帶var 的可以不賦值,但是也相當於給全局對象window增加了一個屬性. 不帶var的必須要賦值,否則就會去找全局對象window上是否有這個屬性,沒有這個屬性就會報錯.

    • 用逗號分隔的表示連var;如:var a = 1,b = 2,c = 3;
    • 用分號(分號代表代碼段)來分隔的,前面帶var的屬於變量,不帶var的相當於給全局對象window添加了屬性;如:var a = 1;b = 2;c = 3;
    • 連等 帶var的是一個變量,其他的不帶var的就相當於給全局對象window添加了屬性
  • ==變量提升只發生在=左邊==
  • ==return後面的內容不進行變量提升 但是下面的 代碼要進行變量提升==
function f3(){
    console.log(f4());//打印f3函數體中的內容
    console.log(f2());//報錯f2沒有進行變量提升
    return function f2(){
    //return 後面的內容不進行變量提升 但是下面的代碼要進行變量提升
    }
    function f4(){
        console.log(f3);
    }
}
f3();
var a = [1];
b = a;
b[1] = ‘a‘;//b = [1,‘a‘]
console.log(a);//[1,‘a‘] b指向了a的地址,修改的時候修改了地址中的屬性以及屬性值
  • 變量名重復:不再進行聲明,但是要重新定義 (函數名跟變量名重復取函數名、函數名和函數名重復會覆蓋)
  • 函數當做參數的時候,不進行變量提升
  • 匿名函數不進行變量提升
  • 自執行函數不會進行變量提升
  • let const聲明的變量不進行變量提升

    函數的定義與執行

  • 定義的三步曲:
  • 開辟新的堆內存
  • 存儲代碼字符串
  • 返回內存空間地址
  • 函數執行過程:
  • 首先會形成一個私有作用域,開辟一個棧內存
  • 形參賦值
  • 變量提升
  • 代碼從上到下執行
  • 作用域是否銷毀
  • 對象的定義:
  • 開辟一個空間地址,堆內存
  • 把鍵值對存儲到堆內存下
  • 把空間地址賦值給對象名
console.log(fn);//fn()
console.log(f);//undefined
function fn(){}//函數聲明和定義
var f = function(){}//函數表達式-->箭頭函數
console.log(fn);//fn函數體
console.log(f);//undefined
console.log(fn());//打印兩次undefined 函數執行的時候打印f為undefined,並且函數沒有返回值 打印一次undefined
function fn(){
console.log(f);
}
var f = function(){}//函數聲明
console.log(f2);//f2未定義 報錯
var 
var f = function f2(){}
console.log(f2)//f2未定義 報錯
setTimeout(funtion f2(){},1000)//函數作為參數的時候不進行變量提升

函數聲明提升

1、函數的兩種創建方式
  • 函數聲明
  • 函數表達式

函數聲明的語法

f(‘nihao‘);
function f(name){
    console.log(name);
}
//能打印出nihao

函數表達式語法

f(‘nihao‘);
var f = function (name){
console.log(name);
}
//控制臺報錯 Uncaught ReferenceError:f id not function錯誤顯示f不是一個函數

兩種方式的區別:

  • 函數聲明又一個非常重要的特征:函數聲明提升,函數聲明語句將會被外部腳本或者外部函數作用域的頂部(跟變量提升非長相似)。正是這個特征,所以可以把函數聲明放在調用它的語句後面。
var getName = function (){
console.log(2);
}
function getName(){
console.log(1);
}
getName();
//打印出2

這個例子涉及到了變量聲明提升函數聲明提升.正如前面提及到的函數聲明提升,函數聲明function getName(){}的聲明會被提前到頂部.而函數表達式var getName = function(){}則表現出變量聲明提升.因此,在這種情況下,getName也是一個變量,這個變量的聲明將被提升到底部,而變量的賦值依然保留在原來的位置.需要註意的是:函數優先,雖然函數聲明和變量聲明都會被提升,但是函數會首先被提升,然後才是變量。因此上面的函數可以換成這個樣子

function getName(){
//函數聲明提升到頂部
console.log(1);
}
var getName;//變量聲明提升
getName = function(){
//變量賦值依然保留在原來的位置
console.log(2);
}
getName();//最終輸出2

在原來的例子中,函數聲明雖然是在函數表達式之後,但是由於函數聲明提升到頂部,因此後面getName又被函數表達式的賦值操作給覆蓋了,所以控制臺輸出了2
技術分享圖片
技術分享圖片

console.log(f);//打印函數體
function f(){
    console.log(1);
}
f();//88
function f(){
    console.log(2);
}
function f(){
    console.log(3);
}
f();//88
f = 99;
function f(){
    console.log(88);
}
f();//f is not a function 
console.log(f);

ES6的let和const

var 與ES6中const 、let聲明的變量的區別
https://blog.csdn.net/qq_22855325/article/details/72843456

let不能和函數重名

  • const聲明的變量,
  • 如果是基本數據類型,那麽不可以進行數據修改.
  • 如果 是引用數據類型值,就可以操作引用地址,不可以替換引用地址
  • 沒有變量提升
  • 不可以重復聲明
  • 定義的變量不會給window增加屬性
  • 定義的是個常量,定義之後不可以修改
  • 一旦聲明必須賦值
  • let雖然不會進行變量提升,但是會先檢查當前作用域下是否有重復命名
  • 沒有變量提升
  • 不可以重復聲明
  • 定義的變量不會給window增加屬性
var a = 2;
if(‘a‘ in window){
    console.log(a);//形成暫時性死區,即在塊級作用域下,不能提前拿到let聲明的變量的值,打印2
    let a = 1;
}
let

ES6中提出了一個新的變量,不在於取代var,而在於解決ES5中var聲明中的一些痛點;這就是let
let的特點

  • 1、let是塊級變量,不存在於window下[非全局屬性],window,變量名是找不到的,它的作用範圍就那麽一小塊
  • 2、let不允許重新聲明同名變量,會拋出異常,具有唯一性
  • 3、let不允許沒聲明就使用,會拋出異常,只有執行該聲明的時候才能使用
  • 4、let有自己特色的閉包特性,比如在for循環的應用中
//1-
let tt = ‘nihao‘;
console.log(tt);//打印出‘nihao‘
console.log(window.tt);//打印出undefined

//2-
function test2(){
    var abc = 99;
    let abc = 88;
    console.log(abc);
}
test2();//打印值:Uncaught SyntaxError:Indentifier ‘abc‘ has already been declared

//3-
function test3(){
    console.log(test3);
    let test3 = ‘哈哈哈哈‘;
}
test3();//打印值:Uncaught ReferenceError:test3 is not defined

//4-每一次for村換都重新綁定一次作用域且脫離失效,就是let自身的特色
for(let i = 0;i<9;i++){
    //for循環形成保護機制
    console.log(‘循環內的值是:‘+i);
}
console.log(i);//打印值
//循環內的值是:0
//循環內的值是:1
//循環內的值是:2
//循環內的值是:3
//循環內的值是:4
//循環內的值是:5
//循環內的值是:6
//循環內的值是:7
//循環內的值是:8
//Uncaught ReferenceError:i is not defined  塊級作用域 外界無法訪問

查找上一級的作用域

1、在當前作用域下輸出變量值時,首先觀察是否是私有變量

  • 如何判斷一個變量是私有的
  • 當前變量有沒有被var過和function
  • 形參也是私有變量

2、如果變量不是私有的,就向上一級作用域查找

  • 上一級作用域判斷函數在哪定義的,函數上一級的作用域就是誰,跟函數執行沒有任何關系
  • 但獲取變量值時,首先是否是私有變量,如果不是就向上一級作用域查找,一級一級向上,直到window為止,如果window也沒有,那麽就會報錯,這樣一級一級向上查找作用域就是作用域鏈

    堆內存的銷毀

    形成兩個虛擬內存:棧內存、堆內存
    棧內存:作用域
    引用數據類型
    在JS中的{}[]都是開辟一個新的空間地址
    谷歌瀏覽器:每隔一段時間,自動檢查占用並是否銷毀
    火狐和IE:采用的計數的規則,當堆內存地址被占用一次時,計數+1,否則-1,如果是被占用0次,就回收

    私有作用域的銷毀

  • 函數的執行:形成一個私有的作用域,提供代碼運行環境,存儲基本數據類型

    閉包
  • 保護裏面的私有變量不受外界幹擾
  • 存儲值
  • 保護機制:當前私有作用域中,有引用數據類型被外界所占有,導致當前作用域變成一個不銷毀的作用域,裏面的變量就成了不銷毀的變量

一般情況下,函數執行完成之後,當前作用域就會銷毀
函數沒執行一次就會開辟一個新的私有作用域,並且新的私有作用域和之前的作用域沒有任何關系,是兩個不同的棧內存

  • 不銷毀的作用域:
  • 函數執行return出一個引用的數據類型值
  • 函數執行return出的引用數據類型值並且被外界接收(被占用)

    棧內存

    瀏覽器加載的時候,碰到引用數據類型,都會開辟一個新的內存空間,[對象:鍵值對;函數:代碼字符串],給這個內存空間賦一個16進制內存地址,將這個內存地址指向聲明的變量,這個內存空間就是堆內存
    堆內存的釋放,手動賦值null,[指向空指針];瀏覽器判斷該內存沒有變量就去收回它,就會釋放

function fn(){
    var t = 10;
    return function (){
        console.log(t++)
    }
}
var f = fn();
f();
f();
  • 不立即銷毀:
  • 需要等到裏面的小函數執行完成之後,那麽外層作用域就會銷毀
function fn(){
    var t = 10;
    return function (){
        console.log(t++);
    }
}
fn()();
var i = 0;
function fn(){
    //i = 5 6;
    return function(n){
        console.log(n + i++);
    }
}
var f = fn(5);
f(10);//15
f(20);//26
fn(8)(12);//20
fn()(18);//NaN
function fn (){
var a = 1 ;
return function (){
a++;
console.log(a);
}
}
var f = fn();
f(); //2
fn()(); //2
f(); //3
var obj= {
 i : 10,
fn:(function () {
var i = 0;
return function (n) {
console.log(n + i++)
}
})()
};
var f = obj.fn;
f(10);// 10
f(20);// 21
obj.fn(30);// 32 塊級作用域
obj.fn(40);// 43

this關鍵字

  • 函數中的this,指的就是函數的當前執行主體
  • 1、在全局作用域下,this 指向window
  • 2、函數體中的this,看函數執行前有沒有‘.‘;如果有,那麽‘.‘前面是誰,this就指向誰;如果沒有‘.‘,那麽會指向window
  • 3、如果給元素的事件行為綁定方法,,那麽方法中的this,就會指向當前被綁定的那個元素
  • 4、回調函數中的this指向window
  • 5、自執行函數中的this一般都指向window
  • 6、forEachmap第二個參數可以修改回調函數中的this
  • 7、構造函數中的this指向當前類的實例
  • 8、call、apply、bind可以改變this關鍵字的指向
  • this是誰,和它在哪定義的以及在哪執行的沒有任何關系
    技術分享圖片
    技術分享圖片
    技術分享圖片
function b() {
    console.log(this); //window
}
window.b();
var obj = {
    num:1,
    fn : function () {
        console.log(this);
        function m() {
            console.log(this);// window;
        }
        m()
    }
}
var f = obj.fn;
f(); // window
obj.fn();// obj
var obj = {
    num:1,
    f:{
        num:2,
        fn:function () {
        console.log(this);// obj.f
        }
    }
}
obj.f.fn()
//1.
setInterval(function () {
    console.log(this); // window
},1000)
//2.
(function () {
    console.log(this); //window
})()
//3.
var obj = {
    fn: (function () {
        console.log(this); //window
})()
}
var num =2;// 1 2
var obj = {
    num : 0,
    fn : function () {
        num = 1;
        // this-->obj
        (function (num) {
        // this --> window
            ++this.num;
            num++;
            console.log(num)// 1
        })(this.num)// 0
    }
}
obj.fn();
console.log(window.num,obj.num) //2 0

this的重點練習題

var num =2;// 1 2
var obj = {
     num : 0,
     fn : function () {
     num = 1;
     // this-->obj
    (function (num) {
    // this --> window
        ++this.num;
        num++;
        console.log(num)// 1
    })(this.num)// 0
  }
}
obj.fn();
console.log(window.num,obj.num) //2 0

技術分享圖片
技術分享圖片

設計模式-單例模式

模塊化開發

把一個項目按照頁面或者功能分割成不同的任務,交給項目中不同的成員開發.開發結束之後
將代碼合並到一起.

  • 多人協作開發的問題: 變量名 函數名 沖突
  • 為了防止全局變量汙染: 閉包但是閉包並不完美,所以選擇搭配設計模式來進一步進行
    項目開發

    單例模式
  • 表現形式:就是一個對象:{name:xxx,age:function(){}};
  • 定義:把描述同一件事物的不同屬性放在同一個對象[空間]下,避免了全局變量的幹擾;這種模式就是單例模式
  • 在設計模式當中,這個person不僅僅是一個對象名,還是一個命名空間,多個命名空間是相互獨立的,互不幹擾
  • 好處:不受全局變量的汙染和幹幹擾,並且可以相互調用方法
  • 由來:單例模式的本質就是一個對象,它是object類上的一個實例,實例與實例之間互不幹擾,叫做單獨的實例,簡稱"單例"

    高級單例模式
  • 定義:在高級單例模式當中,我們不只會把一個對象賦值給一個命名空間,我們會先讓它執行一個自執行函數,[就形成了一個閉包,一個不銷毀的作用域],在自執行函數中,返回一個對象給這個命名空間
  • 好處:可以在私有的作用域當中,創建很多的屬性和方法,僅需要把我們使用的屬性和方法暴露在這個對象當中即可。相對於單例模式,可以存儲不同方法中的公有變量

    工廠模式
  • 定義:把實現同一種功能的代碼放進一個函數中,當想實現類似功能時,只需要執行這個函數即可,傳參數不同就可以.
  • 好處:減少了代碼的冗余:"高內聚、低耦合"-->函數的封裝

    面向對象

  • OOP/OP面向對象的縮寫,面向對象思想
  • 定義:面向對象的封裝、繼承和多態,通過簡單的實例化,調用其他的方法和屬性
  • JS就是通過面向對象的思想設計開發出來的
  • 需要了解 對象、類、實例
  • 對象:萬物皆對象,多為一種泛指,可以是任何物體
  • 類:對象中具有同一屬性和特征的集合,類又分為大類和小類
  • 實例:就是類中的一個具體的細分,我們研究當前實例具有哪些屬性和方法,那麽證明當前類中的其他實例也同樣具有

    JS中的內置類
  • JS中的任何數據類型都是它所屬的類,除了null、undefined
  • Number、String、Boolean、Object、Array RegExp、Function、Date...
  • 類的首字母都是大寫
  • 類的執行通過new來執行
  • Object對象類,被稱為基類,在任何數據類型都可以通過__proto__[原型鏈]找到基類Object

    創建類
  • 字面量方式
  • 實例化方式
  • 引用數據類型方式創建 var ary = new Array(‘1‘)
    註意:

    • new Array(10):創建一個長度為10的數組,數組中的每一項都是空
    • new Array(‘10‘):如果只傳遞一個實參,並且實參不是數字,相當於把當前值作為數組的第一項存儲進來
    • new Array(10,20,30):如果傳遞多個實參,不是設置長度,而是把傳遞的內容當做數組中的每一項存儲起來
    構造函數
  • 定義:當一個函數通過new關鍵字來執行的時候,這個函數就不是普通函數了,它是一個構造函數,也是一個自定義類,當前的函數名就是類名,這個函數的返回值就是這個類的實例
  • 為了讓構造函數和普通函數有一個區別,我們建議寫構造函數的時候首字母大寫[類名]
  • 註意:一般情況下,我們寫業務邏輯的時候不會用到構造函數,但是在封裝庫、插件以及組件的時候就會用到構造函數模式
  • 構造函數執行的時候,如果沒有參數的時候,小括號可以不寫
  • let person = new Person

    普通函數和構造函數的區別
  • 相同點:形成私有的作用域-->形參賦值-->變量提升-->從上到下執行-->作用域銷毀
  • 不同點:
    • 構造函數運行時,形成作用域後,在代碼運行之前,首先會給當前的作用域初始化一個空對象;並且讓當前作用域下的this指向這個空對象 當代碼運行結束,構造函數把函數體中的this作為返回值返回
    • 構造函數如果並不需要傳參,可以省略執行的小括號
    • 構造函數中的this,指向當前的實例
    • 在構造函數中,return 一個基本數據類型值,那麽對實例沒有任何影響;如果return出一個引用數據類型值,那麽會把默認returnthis替換掉.

      構造函數的執行過程
  • 形成一個私有的作用域
  • 形參賦值
  • 變量提升
  • 瀏覽器會創建一個對象,[開辟一個新的堆內存],將這個對象指向了this[堆內存指針指向this實例]
  • 代碼從上到下執行
  • 判斷當前構造函數是否有return,
  • 如果沒有return默認將實例返回;
  • 如果有return,
    • 如果return的是基本數據類型,對實例沒有影響
    • 如果是引用數據類型,那麽實例就是該引用數據類型
  • 構造函數中:建議不要輕易return引用數據類型
    技術分享圖片

    私有屬性
  • 在構造函數中,給this添加屬性值和方法,都屬於當前實例的私有屬性

    公有屬性
  • 當前實例通過__proto__找到所有的屬性和方法都輸屬於當前實例的公有屬性
  • 實例想要調取公有屬性,直接可以調取,底層及時通過__proto__去找這個屬性
  • 用in這種方式來判斷,當前屬性名[公有屬性+私有屬性]是都屬於這個對象
    console.log(‘hasOwnProperty‘ in person1);
  • Object類提供一個hasOwnProperty,這個方法判斷當前屬性是否是該實例的私有屬性:返回布爾值console.log(person1.hasOwnProperty("age")) //true console.log(person1.hasOwnProperty("valueof")) //false
    例題:自己封裝一個方法,判斷當前屬性是否是當前實例的一個公有屬性hasPubProperty
function hasPubProperty(obj,item){
        //先檢測是否是屬性
        return item in obj &&!obj.hasOwnProperty(item);
    }
    console.log(hasPubProperty([], ‘toString‘));
JS中的函數
  • 普通函數、類(自定義類和內置類)、函數類的實例

    對象
  • 普通對象(對象數據類型)
  • 構造函數new出來的一個實例,也是一個對象
  • 類上面的原型也是一個對象
  • 函數也是一個對象

    學習原型模式需要記住三句話
  • 所有的函數都天生自帶一個屬性,叫做prototype(原型),它是一個對象,既然是對象,那就是一個堆內存
  • 所有函數的原型上面(都是開辟的這個堆內存),都天生自帶一個屬性,叫做constructor(構造函數),它指向當前類本身
  • 所有的對象都天生自帶一個屬性__proto__,它指向當前類的原型

  • 所有的函數數據類型(普通函數、類(內置的、自定義))都是Function的一個實例;Function是所有函數的基類;
  • 5.所有的對象數據類型(實例、prototype、對象)都是Object的一個實例;Object是所有對象數據類型的基類;
  • Function 首先是自己的一個實例;
    技術分享圖片
function People(name){
    let age = 9;
    this.name = name;
    this.age = age;
}
People.prototype.say = function () {
    console.log(this);
};
let person1 = new People(‘zf‘);
let person2 = new People(‘zhufeng‘);
//person1屬於People類
//__proto__指向類People的原型prototype
console.log(person1.__proto__ == People.prototype);//true

技術分享圖片

原型鏈
  • 定義:一個實例要找屬性,優先會去找自己的私有屬性,如果自己的私有屬性沒有,那就通過__proto__找到自己所屬類的原型上面的公有屬性,如果公有屬性還沒有,繼續通過__proto__找到自己的所屬類的原型直到Object[基類]的原型上,一直找到基類還沒有的話,直接返回undefined

    Object類和Function類
    Function類:
  • 所有的類都是通過函數的方式來創建,由此可以得知,所有的類(包括基類Object)都是函數類的一個實例
  • 判斷一個實例是否屬於一個類:intanceof
    console.log(Number instanceof Function); //true
    console.log(String instanceof Function); //true
    console.log(Object instanceof Function); //true
  • constructor:通過實例來調用這個方法,指向當前類本身
  • 萬物皆對象,JS中的任何數據類型都可以通過proto
    技術分享圖片

JS第一周學習筆記整理