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