1、let函數
let 是用來聲明變量,相似var,可是其聲明的變量,只在聲明的代碼塊內有效。而且不容許在相同做用域內,重複聲明同一個變量;也不能在函數內部從新聲明參數。ui
for(let i =0;i<3;i++){ let tempObj = { name:'tom' } //let tempObj = {} //SyntaxError: Identifier 'tempObj' has already been declared var tempArr = [23] } console.log(tempObj) //tempObj is not defined console.log(tempArr) //[23]
let命令所聲明的變量必定要在聲明後使用,不然報錯。
var命令會發生「變量提高」現象,即變量能夠在聲明以前使用,值爲undefined。this
console.log(a); // 輸出undefined var a= 2; console.log(b); // 報錯ReferenceError let b= 2;
在塊級做用域內部的聲明函數,建議不要使用函數聲明語句;優先使用函數表達式。spa
由於函數聲明相似於var命令,會發生變量提高。即把函數聲明提高到其所在的塊級做用域的頭部。
// 建議不要使用 { let a = 'secret'; function f() { return a; } //至關於 //var f= function () { //f會變量提高 // return a; //} } // 優先使用函數表達式 { let a = 'secret'; let f = function () { return a; }; }
塊級做用域必須有大括號,若是沒有大括號,JavaScript 引擎就認爲不存在塊級做用域。函數聲明也是如此。prototype
if (true) let x = 1; //會報錯 if (true) { //正常 let x = 1; }
2、const指針
聲明一個只讀的常量。一旦聲明,常量的值就不能改變。必須當即初始化,不能留到之後賦值。
其做用域與let命令相同:只在聲明所在的塊級做用域內有效。
const只能保證這個指針是固定的,也就是說對象中的屬性是可變的。
可使用Object.freeze方法。能夠將聲明的對象凍結code
var constantize = (obj) => { Object.freeze(obj); Object.keys(obj).forEach( (key, i) => { if ( typeof obj[key] === 'object' ) { constantize( obj[key] ); } }); };
聲明變量的六種方法對象
var function let const import class
var命令和function命令聲明的全局變量,是頂層對象的屬性;而let、const、class命令聲明的全局變量,並不屬於頂層對象的屬性。blog
var a = 1; window.a // 1 let b = 1; window.b // undefined
js中獲取頂層對象的兩種方法。圖片
function foos() { (typeof window !== 'undefined' ? window : (typeof process === 'object' && typeof require === 'function' && typeof global === 'object') ? global : this); } // 方法二 var getGlobal = function () { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('unable to locate global object'); };
在ES2020 語言標準中,引入globalThis做爲頂層對象。任何環境下,globalThis都是存在的,均可以從它拿到頂層對象,指向全局環境下的this。
//兩次打印的對象是相同的 console.log(globalThis) class Infos { gets() { console.log(globalThis) } } let ss = new Infos(); ss.gets();
3、js原型鏈
一、對象有__proto__屬性,函數有prototype屬性;對象由函數生成。
二、生成對象時,對象的__proto__屬性指向函數的prototype屬性。
三、函數也是對象的一種,因此函數有__proto__屬性
//首先咱們先建立一個構造函數Foo let Foo = function() {} //實例化 let f1= new Foo(); console.log(f1.__proto__ === Foo.prototype) //true //而Foo函數對象都是由Function函數生成的: console.log(Foo.__proto__ === Function.prototype) //true console.log(Foo.prototype.constructor === Foo) //true //Function函數自己做爲對象時,生成它的函數是他自身! console.log(Function.__proto__ === Function.prototype) //true console.log(Function.prototype.constructor === Function) //true //函數默認的prototype是系統自動生成的一個對象: console.log(Foo.prototype.__proto__ === Object.prototype) //true console.log(Function.prototype.__proto__ === Object.prototype) //true //新建對象 let o1= new Object(); //或者 let objs = {} console.log(o1.__proto__ === Object.prototype) //true //Object函數既然是函數,那生成它的函數天然是Function函數 console.log(Object.__proto__ === Function.prototype) //true console.log(Object.prototype.constructor === Object) //true
經過以上的分析能夠得出原型鏈圖,以下圖所示: