摘要:代碼示例語法和方法類似,不同的是,傳入調用函數的參數變成以數組的形式傳入,即改造上面的示例就是方法用于將函數體內的綁定到某個對象,然后返回一個新函數。類型包裝對象數值字符串布爾值在一定條件下,也會自動轉為對象,也就是原始類型的包裝對象。
現在的前端框架層出不窮,3個月就要重新入門一次前端的現狀,讓我們來不及學好基礎就開始上手框架。常常就因為這樣,我們會很快到達基礎基礎技術瓶頸,基礎是所有技術的核心,在跳槽季重新溫故了一遍 javascript 基礎,有收獲,整理出來分享給大家。對象 變量可以當對象使用
javascript 中所有的變量都可以當做對象使用,除了undefined 和 null ,我們測試下
false.toString() // "false" [1,2,3].toString() //"1,2,3" 1..toString() //"1" ({a:"33"}).toString() //"[object Object]"
undefined.toString() //Uncaught TypeError null.toString() //Uncaught TypeError
數值和對象雖然能調用 toString 方法,但是在寫法上需要注意下
number 調用時不能直接數值后面直接調用toString 方法,因為 js 會將點運算符解析為數值的小數點
1.toString() //Uncaught SyntaxError 1..toString() //"1"
對象直接調用toString 方法時,需要用小括號包裹起來,不然js 會將對象的花括號識別成塊,從而報錯
{a:"33"}.toString() // Uncaught SyntaxError ({a:"33"}).toString() // "[object Object]"對象刪除屬性
刪除對象的屬性唯一的方法是使用 delete 操作符,設置元素屬性為 undefined 或則 null 并不能真正刪除,只是移除了屬性和值的關聯
var test = { name:"bbt", age:"18", love:"dog" } test.name = undefined test.age = null delete test.love for (var i in test){ console.log(i+":"+test[i]) }
運行結果
name:undefined age:null undefined
只有 love 被正則刪除,name 和 age 還是能被遍歷到
構造函數在 javascript 中,通過關鍵字 new 調用的函數就被認為是構造函數,我們可以通過構造函數創建對象實例
但是在使用過程中你一定發現了,每實例化一個對象,都會在實例對象上創造構造函數的方法和屬性。倘若創建的實例比較多,重復創建同一個方法去開辟內存空間就會顯得十分浪費,我們可以通過把被經常復用的方法放在原型鏈上。
原型繼承javascript 和一些我們所了解的面向對象編程的語言不太一樣,在 es6 語法以前,我們是通過原型鏈來實現方法和屬性的繼承
function Child(){ this.name = "bbt" } Child.prototype = { title:"baba", method: function() {} }; function Grandson(){} //設置 Grandson 的 prototype 為 Child 的實例 Grandson.prototype = new Child() //為 Grandson 的原型添加添加屬性 age Grandson.prototype.age = 40 // 修正 Grandson.prototype.constructor 為 Grandson 本身 Grandson.prototype.constructor = Grandson; var xiaomin = new Grandson() //原型鏈如下 xiaomin // Grandson的實例 Grandson.prototype // Child的實例 Grandson.prototype //{title:"baba",...} Object.prototype {toString: ... /* etc. */};
對象的屬性查找,javascript 會在原型鏈上向上查找屬性,直到查到 原型鏈頂部,所以,屬性在原型鏈的越上端,查找的時間會越長,查找性能和復用屬性方面需要開發者自己衡量下。
獲取自身對象屬性hasOwnProperty 方法能夠判斷一個對象是否包含自定義屬性,而不是在原型鏈上的屬性
var test = {hello:"123"} Object.prototype.name = "bbt" test.name //"bbt" test.hasOwnProperty("hello") //true test.hasOwnProperty("name") //false
for in 循環可以遍歷對象原型鏈上的所有屬性,如此我們將 hasOwnProperty 結合循環for in 能夠獲取到對象自定義屬性
var test = {hello:"222"} Object.prototype.name = "bbt" for(var i in test){ console.log(i) // 輸出兩個屬性,hello ,name } for(var i in test){ if(test.hasOwnProperty(i)){ console.log(i)//只輸出 hello } }
除了上面的方法,getOwnPropertyNames 和 Object.keys 方法,能夠返回對象自身的所有屬性名,也是接受一個對象作為參數,返回一個數組,包含了該對象自身的所有屬性名。
var test = {hello:"222"} Object.prototype.name = "bbt" Object.keys(test) //["hello"] Object.getOwnPropertyNames(test) //["hello"]
那 getOwnPropertyNames 和 Object.keys 的用法有什么區別呢
Object.keys方法只返回可枚舉的屬性,Object.getOwnPropertyNames 方法還返回不可枚舉的屬性名。
var a = ["Hello", "World"]; Object.keys(a) // ["0", "1"] Object.getOwnPropertyNames(a) // ["0", "1", "length"] // length 是不可枚舉屬性函數 函數聲明的變量提升
我們通常會使用函數聲明或函數賦值表達式來定義一個函數,函數聲明和變量聲明一樣都存在提升的情況,函數可以在聲明前調用,但是不可以在賦值前調用
函數聲明
foo(); // 正常運行,因為foo在代碼運行前已經被創建 function foo() {}
函數表達式
foo; // "undefined" foo(); // 出錯:TypeError var foo = function() {};
變量提升是在代碼解析的時候進行的,foo() 方法調用的時候,已經在解析階段將 foo 定義過了。賦值語句只在代碼運行時才進行,所以在賦值前調用會報錯
一種比較少用的函數賦值操作,將命名函數賦值給一個變量,此時的函數名只對函數內部可見
var test = function foo(){ console.log(foo) //正常輸出 } console.log(foo) //Uncaught ReferenceErrorthis 的工作原理
在 javascript 中 ,this 是一個比較難理解的點,不同的調用環境會導致 this 的不同指向,但是唯一不變的是 this 總是指向一個對象
簡單的說,this 就是屬性和方法當前所在的對象(函數執行坐在的作用域),平時使用的 this 的情況可以大致分為5種
調用方式 | 指向 |
---|---|
1. 全局范圍調用 | 指向 window 全局對象 |
2. 函數調用 | 指向 window 全局變量 |
3. 對象的方法調用 | 指向方法調用的對象 |
4. 構造函數調用 | 指向構造函數創建的實例 |
5. 通過,call ,apply ,bind 顯示的指定 this指向 | 和傳參有關 |
Function.call
語法:function.call(thisArg, arg1, arg2, …),thisArg表示希望函數被調用的作用域,arg1, arg2, …表示希望被傳入函數額參數 , 如果參數為空、null和undefined,則默認傳入全局對象。
代碼示例
var name = "xiaomin" var test = {name : "bbt"} function hello( _name ){ _name ?console.log(this.name,_name): console.log(this.name) } hello() //xiaomin hello.call(test) //bbt hello.call(test,"xiaohong") //bbt xiaohong hello.call() //xiaomin hello.call(null) //xiaomin hello.call(undefined) //xiaomin
Function.apply
語法和call 方法類似,不同的是,傳入調用函數的參數變成以數組的形式傳入,即 func.apply(thisArg, [argsArray])
改造上面的示例就是
hello.apply(test,["xiaomin"])
Function.bind
bind方法用于將函數體內的this綁定到某個對象,然后返回一個新函數。
var d = new Date(); d.getTime() var print = d.getTime; //賦值后 getTime 已經不指向 d 實例 print() // Uncaught TypeError
解決方法
var print = d.getTime.bind(d)
容易出錯的地方
容易出錯的地方,函數調用,this 總是指向 window 全局變量,所以在對象的方法里如果有函數的調用的話(閉包的情況),this 是會指向 全局對象的,不會指向調用的對象,具體示例如下
var name = "xiaomin" var test = { name : "bbt" } test.method = function(){ function hello(){ console.log(this.name) } hello() } // 調用 test.method() // 輸出 xiaomin
如果需要將 this 指向調用的對象,可以將對象的 this 指向存儲起來,通常我們使用 that 變量來做這個存儲。改進之后的代碼
var name = "xiaomin" var test = { name : "bbt" } test.method = function(){ var that = this function hello(){ console.log(that.name) } hello() } // 調用 test.method() // 輸出 bbt閉包和引用
閉包我們可以理解成是在函數內部定義的函數
在 javascript 中,內部作用域可以訪問到外部作用域的變量,但是外部作用域不能訪問內部作用域,需要訪問的時候,我們需要通過創建閉包,來操作內部變量
function test(_count){ var count = _count return { inc:function(){ count++ }, get:function(){ return count } } } var a = test(4) a.get()//4 a.inc() a.get()//5
閉包中常會出錯的面試題
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 0); }
很多同學會覺得,上面的代碼會正常輸出0到9,但是實際是輸出十次10。遇到這個題目,除了閉包的概念要理解清楚,你還需要知道,setTimeout 內的代碼會被異步執行,代碼會先執行所有的同步代碼,即上面的這段代碼會先將 for 循環執行,此時 i 的值為 10,console.log(i) 一直引用著全局變量的 i 所以會輸出十次 10
改進代碼,我們在 for 循環里創建一個閉包,把循環自增的 i 作為參數傳入
for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i); }setTimeout && setInterval
javascript 是異步的單線程運行語言,其他代碼運行的時候可能會阻塞 setTimeout && setInterval 的運行
console.log(1) setTimeout(function(){ console.log(2) }, 0); console.log(3) 輸出結果: 1,3,2 //setTimeout 被阻塞
處理阻塞的方法是將setTimeout 和 setInterval放在回調函數里執行
function test(){ setTimeout(function(){ console.log(2) }, 0); }
setTimeout 和 setInterval 被調用時會返回一個 ID 用來清除定時器
手工清除某個定時器
var id = setTimeout(foo, 1000); clearTimeout(id);
清楚所有的定時器
var lastId = setTimeout(function(){ console.log("11") }, 0); for(var i=0;i獲取最后一個定時器的id,遍歷清除定時器,可以清除所有的定時器。
類型 包裝對象數值、字符串、布爾值——在一定條件下,也會自動轉為對象,也就是原始類型的“包裝對象”。我們可以通過構造函數,將原始類型轉化為對應的對象即包裝對象,從而是原始類型能夠方便的調用某些方法
數值,字符串,布爾值的類型轉換函數分別是 Number,String,Boolean,在調用的時候在函數前面加上New 就變成了構造函數,能夠蔣對應的原始類型轉化為“包裝對象”
var v1 = new Number(123); var v2 = new String("abc"); var v3 = new Boolean(true); typeof v1 // "object" typeof v2 // "object" typeof v3 // "object" v1 === 123 // false v2 === "abc" // false v3 === true // false類型轉換類型轉換分為強制類型轉換和自動轉換,javascript 是動態類型語言,在到嗎解析運行時,需要的數據類型和傳入的數據類型不一致的時候,javascript 會進行自動類型轉化。當然,你也可以通過類型轉換方法進行強制類型裝換。
日常開發中,我們最常用的數據類型自動轉換不過就下面三種情況
不同數據類型之間相互運算
"2"+4 // "24"對非布爾值進行布爾運算
if("22"){ console.log("hello") }對非數據類型使用一元運算符
+"12" //12我們也通過 Number ,String,Boolean 來進行強制數據類型轉換。強制類型轉化的規則有點復雜,我們來了解一下。
Number 轉換 引用阮老師的詳細解釋
第一步,調用對象自身的valueOf方法。如果返回原始類型的值,則直接對該值使用Number函數,不再進行后續步驟。 第二步,如果 valueOf 方法返回的還是對象,則改為調用對象自身的 toString 方法。如果 toString 方法返回原始類型的值,則對該值使用 Number 函數,不再進行后續步驟。 第三步,如果 toString 方法返回的是對象,就報錯。String 轉換方法同樣也是通過調用原對象的 toString 方法和 valueOf 方法,但是不同的是 String 函數會先調用 toString 方法進行轉換
Boolean 的轉換規則會相對簡單一些,除了幾個特殊的值,都會被轉化為 true
undefined null +0或-0 NaN ""(空字符串)但是要注意
Boolean("false") //truetypeoftypeof 操作符返回數據類型,但是由于 javascript 設計的歷史原因,typeof 現已經不能滿足我們現在對于類型判斷的要求了
Value Class Type "foo" String string new String("foo") String object 1.2 Number number new Number(1.2) Number object true Boolean boolean new Boolean(true) Boolean object new Date() Date object new Error() Error object [1,2,3] Array object new Array(1, 2, 3) Array object new Function("") Function functio /abc/g RegExp object (function in Nitro/V8) new RegExp("meow") RegExp object (function in Nitro/V8) {} Object object new Object() Object object null null object 我們可以看到,typeof 不能區分對象的數組和日期,還會把 null 判斷成對象,那我們一般是什么時候用 typeof 呢。我們可以用來判斷一個已經定義的變量是否被賦值。
var a if(typeof a == "undefined"){ console.log("a 已經被定義") }instanceofinstanceof 操作符通常用來判斷,一個對象是否在另一個對象的原型鏈上,需要注意的是 instanceof 的左值是對象,右值是構造函數// defining constructors function C() {} function D() {} var o = new C(); // true, because: Object.getPrototypeOf(o) === C.prototype o instanceof C; // false, because D.prototype is nowhere in o"s prototype chain o instanceof D;#### Object.prototype.toString
那么我們有沒有可以用來區分變量數據類型的方法呢,有,Object.prototype.toString一些原始數據類型也有 toString 方法,但是通常他們的 toString 方法都是改造過的,不能進行 數據類型判斷,所以我們需要用 Object 原型鏈上的 toString 方法
var a = 1234 a.toString() // "1234" Object.prototype.toString.call(a) // "[object Number]"不同類型返回的結果如下:
1. 數值 [object Number] 2. 字符串 [object String] 3.布爾值 [object Boolean] 4.undefined [object undefined] 5.null [object Null] 6.數組 [object Array] 7.arguments [object Arguments] 8.函數 [object function] 9.Error [object Error] 10.Date [object Date] 11.RegExp [object RegExp] 12.其他對象 [object object]那么我們就能夠通過 Object.prototype.toString 方法,封裝一個可以判斷變量數據類型的函數了
function type(obj) { return Object.prototype.toString.call(obj).slice(8, -1); } type(function(){}) //"Function"這次我們從對象、函數、類型三方面入手了解了javascript 中容易被忽視或則說比較難理解的地方,我會繼續將我在學習中積累的內容分享給大家,如果大家覺得文章有需要改進或則有其他想要了解的內容的,歡迎私信,評論或則微信我,646321933
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/93934.html
摘要:通過拆箱轉換,把對象編程基本類型,再從從基本類型轉換成對應的或者。拆箱轉換會嘗試調用和來獲得拆箱后的基本類型。 undefined和null ??Undefined類型表示未定義,它的類型只有一個值為undefined。任何變量在賦值前都是undefined類型,值為undefined。但是JS中undefined是一個變量,并非是一個關鍵字,為了避免無意中的篡改,使用void 0來獲...
摘要:這兩個方法的參數是一致的,回調函數和執行回調函數時使用的值,回調函數中的參數也是一致的,分別是數組當前元素當前元素索引和數組本身。 青湛(GitHub/mintsweet) 原文鏈接 前言 自以為還算一個比較高產的人吧~但是感覺好久都沒有寫點什么沒有營養的東西了,這一篇本來是打算去年年底都要拿出來說一說的,但是年底事情太多了,加上我真的變懶了拖到現在才要把這個準備了好久的標題完善一下...
摘要:強制類型轉換本章介紹了的數據類型之間的轉換即強制類型轉換包括顯式和隱式。強制類型轉換常常為人詬病但實際上很多時候它們是非常有用的。隱式強制類型轉換則沒有那么明顯是其他操作的副作用。在處理強制類型轉換的時候要十分小心尤其是隱式強制類型轉換。 前言 《你不知道的 javascript》是一個前端學習必讀的系列,讓不求甚解的JavaScript開發者迎難而上,深入語言內部,弄清楚JavaSc...
摘要:基于工廠角色和產品角色的多態性設計是工廠方法模式的關鍵。工廠方法模式之所以又被稱為多態工廠模式,是因為所有的具體工廠類都具有同一抽象父類。工廠方法模式總結工廠方法模式是簡單工廠模式的進一步抽象和推廣。 JavaScript工廠模式 首先需要說一下工廠模式。工廠模式根據抽象程度的不同分為三種 簡單工廠模式 工廠方法模式 抽象工廠模式 1.簡單工廠模式 簡單工廠模式:又稱為靜態工廠方法...
摘要:的碼點被稱為基本字符區域。關于的介紹,我準備用文檔阮一峰來做一些介紹,具體的可以參考文檔引入的原因的對象屬性名都是字符串,這容易造成屬性名的沖突。其他的一些屬性可以去看文檔阮一峰注意函數前不能使用命令,否則會報錯。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完...
閱讀 3674·2021-11-15 11:37
閱讀 2322·2021-09-24 10:39
閱讀 2462·2021-07-25 21:37
閱讀 1450·2019-08-30 15:56
閱讀 2589·2019-08-30 15:55
閱讀 958·2019-08-30 15:54
閱讀 2129·2019-08-30 14:21
閱讀 859·2019-08-30 11:24