摘要:我們都說構(gòu)造函數(shù)開頭首字母大寫但那只是人為的規(guī)定并不是語法。只是一個操作符,任何函數(shù)都能通過來執(zhí)行,并不只是構(gòu)造函數(shù),只不過我們認(rèn)為之后的都是構(gòu)造函數(shù)。
這一篇文章主要是講述一些有關(guān)js的小知識點。因為我也不是很精通哪一方面只能把自己知道的一點點寫出來。取名大雜燴也是這意思吧,既然是道菜那么就來嘗嘗我的手藝吧。
第一道菜
1.首先,我想說一下事件綁定。
事件綁定我們都知道有:on + "type"的事件綁定還有addEventListener的事件綁定。
在以前因為各種原因?qū)е挛覀冊诓煌臑g覽器上面實現(xiàn)一樣的功能出現(xiàn)了兼容的寫法,首先我們先來看看事件綁定的兼容寫法。
function bindEvent(obj, type, handle) { if(window.addEventListener){ obj.addEventListener(type, handle, false); } if(window.attachEvent){ // IE obj.attachEvent("on" + type, handle); } obj["on" + type] = handle; }
事件解除除了on + "type"其他的就是怎么綁定怎么解除。
function delEvent(obj, type, handle) { if(window.removeEventListener){ obj.removeEventListener(type, handle, false); } if(window.detachEvent){ // IE obj.attachEvent("on" + type, handle); } obj["on" + type] = null; }
順帶提一下IE與其它瀏覽器獲取target和event的兼容方式。
function handle(e){ let event = e || window.event; // IE let target = e.target || e.srcElement; }
下一篇我會詳細(xì)介紹DOM事件綁定和DOM事件等級。
第二道菜
2.這個知識點我們來說一下繼承。
說到j(luò)s的繼承,我是學(xué)后端的在C ++ 、Java里面都跟js的繼承不一樣,所以一開始不好理解也覺得怪怪的。雖然ES6形式上有點像吧。那我們先來看看js一開始的繼承。
function Father(){ this.a = 1; } Father.prototype.show = function () { console.log(this.a); } function Son(){ Father.call(this); } let son = new Son(); console.log(son.a); console.log(son.show());
我們可以發(fā)現(xiàn)這種是拿不到父級原型上的函數(shù)的。
我們再來看看第二種
function Father(){ this.a = 1; } Father.prototype.show = function () { console.log(this.a); } function Son(){ Father.call(this); } Son.prototype = Father.prototype; //多了這一行 let son = new Son(); console.log(son.a); console.log(son.show());
我們發(fā)現(xiàn)拿到了原型上的函數(shù),但這樣就是最好的了嗎?我們一起來看看。當(dāng)我們查看Son的時候發(fā)現(xiàn)了一個奇怪的事。
我們可以看到Son的constructor變成了Father,這是為什么呢?因為constructor是原型上的函數(shù),我們改變了Son的原型,因為Father的constructor是Father所以Son的constructor就變成了Father。而且這種方法我們改變Son.prototype時Father.prototype也會改變,那這說明我們的方法還是不夠完美。
我們再來看看第三種
function Father(){ this.a = 1; } Father.prototype.show = function () { console.log(this.a); } function Son(){ Father.call(this); } function F(){}; //借用中間層來防止Son改變Father的原型 F.prototype = Father.prototype; Son.prototype = new F(); Son.prototype.constructor = Son; //改變Son的constructor let son = new Son(); console.log(son.a); console.log(son.show()); console.log(son.constructor);
說到了構(gòu)造函數(shù)那我們就看看什么是構(gòu)造函數(shù)。
function Father(){ this.a = 1; } ```這個是不是構(gòu)造函數(shù)?如果說是那你就錯了,因為你思維固定了。我們都說構(gòu)造函數(shù)開頭首字母大寫但那只是人為的規(guī)定并不是語法。還有如果有人問你```this```是誰,你可以放肆的告訴他,你沒調(diào)用我知道是誰啊。```new```只是一個操作符,任何函數(shù)都能通過new來執(zhí)行,并不只是構(gòu)造函數(shù),只不過我們認(rèn)為```new```之后的都是構(gòu)造函數(shù)。 + 那你知道```new```的時候發(fā)生了什么嗎?我們一般都說四步走 + 首先創(chuàng)建一個新的對象。 + 改變這個對象的this + 改變這個對象的原型 + 返回這個對象 我們試著寫一寫
function myNew(){ let obj = {}; let Constructor = arguments[0]; obj.__proto__ = Constructor.prototype; Constructor.apply(obj, arguments); return obj; } let a = myNew(Son); console.log(a); ```
補(bǔ)充:
我們都知道ES6那么他的繼承跟我們的繼承有什么區(qū)別呢?我們來看一下ES6的繼承。
class Father { constructor(){ this.a = 1; } show(){ console.log(this.a); } } class Son extends Father { constructor(){ super(); } } let son = new Son(); console.log(son.a); console.log(son.show());
我們發(fā)現(xiàn)是一樣的。只不過是這種實現(xiàn)方式更加讓人容易理解并且接受尤其是對于習(xí)慣了C++/Java之類語言的人。
其實class這種實現(xiàn)方式只是一個‘語法糖’,當(dāng)我們用typeof Son的時候我們發(fā)現(xiàn)他是一個function,其實它就是一個函數(shù)只不過更加語義化了,而且里面定義的方法其實是定義在了它的原型上面,我們輸出一下Father看看。
第三道菜
3.我們再來介紹一下call、bind、apply
它們都是用來改變this的,只不過有一些小的差別。
call和apply除了傳參方式的不同外,沒有不同的地方。
bind返回一個函數(shù),call、apply立即執(zhí)行。
演示我覺得應(yīng)該不用了吧,因為我不是在寫文檔,那么我們說一些什么呢,就說說怎么模擬實現(xiàn)吧。我這里用的是ES6的語法,我只是覺得這樣寫比較簡單但總體思路不變。
下面以這個為例:
var a = 3; var obj = { a: 1 } function show(g) { console.log(this.a, g); }
call
Function.prototype.callh = function(context){ let args = [...arguments].slice(1); //首先獲取到傳遞的參數(shù) context.fn = this; // 獲取當(dāng)前的調(diào)用者,并添加一個方法 context.fn(...args); // 傳入?yún)?shù) delete context.fn; //刪除新增的函數(shù) } show.callh(obj, 2);
apply
Function.prototype.applyh = function(context){ let args = arguments[1]; // 跟call一樣,只不過apply傳進(jìn)來的是數(shù)組,所以arguments[1]指的是后面的參數(shù) context.fn = this; context.fn(...args); delete context.fn; show.applyh(obj, [2]); }
bind(重點)
// 簡易版 Function.prototype.bindh = function(context){ let args = [...arguments].slice(1); let that = this; return function (argument) { // bind返回一個函數(shù) let args2 = [...arguments].slice(0); that.call(context, ...args.concat(args2)); } } show.bindh(obj)(5);
但上面bind的方式有一點錯誤。我們來看看js里面的bind和我們的在new之后有什么區(qū)別。
上面是js的后面是模擬的??吹搅税?。
因為原型的原因,我們來改進(jìn)一下。
Function.prototype.bindh = function(context){ let args = [...arguments].slice(1); let that = this; function bnd(){} let fn = function (argument) { let args2 = [...arguments].slice(0); return that.call(this instanceof fn ? this : context, ...args.concat(args2)); } bnd.prototype = this.prototype; fn.prototype = new bnd(); return fn; }
這樣就行了。
第四道菜
4.再來講一講this
this一直是我們困惑的問題,有時候能看懂但代碼一多,調(diào)用一多,我們就蒙了,下面我來簡單介紹一下。
在默認(rèn)情況下this指向window(非嚴(yán)格模式)
誰調(diào)用指向誰
call.apply
bind
new
我想到的差不多就這幾種吧,你或許會發(fā)現(xiàn)其實是按this綁定的優(yōu)先級升序排序的。如果你看懂了bind的模擬實現(xiàn)也許會知道為什么bind的優(yōu)先級會高于call、apply。我覺得弄清楚這些this應(yīng)該不是多大的問題吧,來一段代碼看看。
var a = 3; var obj = { a: 1, fn(){ console.log(this.a); } + } function show() { console.log(this.a); } show(); //3 obj.fn(); //1 show.call(obj); // 1 show.apply(obj); // 1 show.bind(obj)(); // 1 show.bind(window).call(obj); //3 bind優(yōu)先級高,跟綁定順序沒區(qū)別
希望這些菜能滿足您的胃口,但愿也能給您填飽一些肚子。我以后還會繼續(xù)努力提高自己的廚藝,希望嘗到這個菜的人都會喜歡。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/100698.html
摘要:前言這段時間突然發(fā)現(xiàn)原生好多東西都忘記了但有些東西確實很重要所以又重新再梳理一次。 showImg(https://segmentfault.com/img/bVbqqkr?w=874&h=382); 前言 這段時間突然發(fā)現(xiàn)JS原生好多東西都忘記了,但有些東西確實很重要,所以又重新再梳理一次。主要有函數(shù)的3種定義方法,ES5函數(shù)this指向,call與appl用法,JS常見的4種設(shè)計模...
摘要:相當(dāng)于繞過了瀏覽器端,自然就不存在跨域問題。三者的區(qū)別與服務(wù)器的交互數(shù)據(jù)始終在同源的請求中攜帶即使不需要,即在瀏覽器和服務(wù)器間來回傳遞。而和不會自動把數(shù)據(jù)發(fā)給服務(wù)器,僅在本地保存。和雖然也有存儲大小的限制,但比大得多,可以達(dá)到或更大。 本文提供最簡便的解答方式,方便快速記憶,復(fù)盤,詳細(xì)答案可自己再搜一下。 js基礎(chǔ)知識 1. javascript typeof返會的數(shù)據(jù)類型有哪些 ob...
摘要:探討判斷橫豎屏的最佳實現(xiàn)前端掘金在移動端,判斷橫豎屏的場景并不少見,比如根據(jù)橫豎屏以不同的樣式來適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗。 探討判斷橫豎屏的最佳實現(xiàn) - 前端 - 掘金在移動端,判斷橫豎屏的場景并不少見,比如根據(jù)橫豎屏以不同的樣式來適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗。 判斷橫豎屏的實現(xiàn)方法多種多樣,本文就此來探討下目前有哪些實現(xiàn)方法以及其中的優(yōu)...
摘要:直搗黃龍黃龍即黃龍府,轄地在今吉林一帶,應(yīng)該是指長春市農(nóng)安縣,為金人腹地。一直打到黃龍府。指搗毀敵人的巢穴。有人會說組合優(yōu)于繼承的。的變更會自動更新依賴的組件。可以操作對象實例,的變更會自動更新組件,屬性設(shè)置方法調(diào)用。 刀耕火種 刀耕火種是新石器時代殘留的農(nóng)業(yè)經(jīng)營方式。又稱遷移農(nóng)業(yè),為原始生荒耕作制。 var TodoApp = Nuclear.create({ add: f...
閱讀 2896·2021-10-14 09:50
閱讀 1235·2021-10-08 10:21
閱讀 3669·2021-10-08 10:16
閱讀 3073·2021-09-27 14:02
閱讀 3149·2021-09-23 11:21
閱讀 2142·2021-09-07 10:17
閱讀 417·2019-08-30 14:00
閱讀 2126·2019-08-29 17:26