總結了一周學習Js的筆記、關於git、GitHub、this、作用域等 ...
目錄
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、
forEach
、map
第二個參數可以修改回調函數中的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
出一個引用數據類型值,那麼會把預設return
的this
替換掉.構造函數的執行過程
- 構造函數運行時,
- 形成一個私有的作用域
- 形參賦值
- 變數提升
- 瀏覽器會創建一個對象,[開闢一個新的堆記憶體],將這個對象指向了
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