亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JS 兼容、繼承、bind、this

YacaToy / 3307人閱讀

摘要:我們都說構(gòu)造函數(shù)開頭首字母大寫但那只是人為的規(guī)定并不是語法。只是一個(gè)操作符,任何函數(shù)都能通過來執(zhí)行,并不只是構(gòu)造函數(shù),只不過我們認(rèn)為之后的都是構(gòu)造函數(shù)。

這一篇文章主要是講述一些有關(guān)js的小知識(shí)點(diǎn)。因?yàn)槲乙膊皇呛芫囊环矫嬷荒馨炎约褐赖囊稽c(diǎn)點(diǎn)寫出來。取名大雜燴也是這意思吧,既然是道菜那么就來嘗嘗我的手藝吧。

第一道菜

1.首先,我想說一下事件綁定。
事件綁定我們都知道有:on + "type"的事件綁定還有addEventListener的事件綁定。

在以前因?yàn)楦鞣N原因?qū)е挛覀冊(cè)诓煌臑g覽器上面實(shí)現(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;
}

下一篇我會(huì)詳細(xì)介紹DOM事件綁定和DOM事件等級(jí)。

第二道菜

2.這個(gè)知識(shí)點(diǎn)我們來說一下繼承。

說到j(luò)s的繼承,我是學(xué)后端的在C ++ 、Java里面都跟js的繼承不一樣,所以一開始不好理解也覺得怪怪的。雖然ES6形式上有點(diǎn)像吧。那我們先來看看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)這種是拿不到父級(jí)原型上的函數(shù)的。

我們?cè)賮砜纯吹诙N

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的時(shí)候發(fā)現(xiàn)了一個(gè)奇怪的事。


我們可以看到Son的constructor變成了Father,這是為什么呢?因?yàn)閏onstructor是原型上的函數(shù),我們改變了Son的原型,因?yàn)镕ather的constructor是Father所以Son的constructor就變成了Father。而且這種方法我們改變Son.prototype時(shí)Father.prototype也會(huì)改變,那這說明我們的方法還是不夠完美。

我們?cè)賮砜纯吹谌N

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è)是不是構(gòu)造函數(shù)?如果說是那你就錯(cuò)了,因?yàn)槟闼季S固定了。我們都說構(gòu)造函數(shù)開頭首字母大寫但那只是人為的規(guī)定并不是語法。還有如果有人問你```this```是誰,你可以放肆的告訴他,你沒調(diào)用我知道是誰啊。```new```只是一個(gè)操作符,任何函數(shù)都能通過new來執(zhí)行,并不只是構(gòu)造函數(shù),只不過我們認(rèn)為```new```之后的都是構(gòu)造函數(shù)。
+ 那你知道```new```的時(shí)候發(fā)生了什么嗎?我們一般都說四步走
+ 首先創(chuàng)建一個(gè)新的對(duì)象。
+ 改變這個(gè)對(duì)象的this
+ 改變這個(gè)對(duì)象的原型
+ 返回這個(gè)對(duì)象
我們?cè)囍鴮懸粚?/pre>
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)是一樣的。只不過是這種實(shí)現(xiàn)方式更加讓人容易理解并且接受尤其是對(duì)于習(xí)慣了C++/Java之類語言的人。
其實(shí)class這種實(shí)現(xiàn)方式只是一個(gè)‘語法糖’,當(dāng)我們用typeof Son的時(shí)候我們發(fā)現(xiàn)他是一個(gè)function,其實(shí)它就是一個(gè)函數(shù)只不過更加語義化了,而且里面定義的方法其實(shí)是定義在了它的原型上面,我們輸出一下Father看看。

第三道菜

3.我們?cè)賮斫榻B一下call、bind、apply

它們都是用來改變this的,只不過有一些小的差別。

call和apply除了傳參方式的不同外,沒有不同的地方。

bind返回一個(gè)函數(shù),call、apply立即執(zhí)行。

演示我覺得應(yīng)該不用了吧,因?yàn)槲也皇窃趯懳臋n,那么我們說一些什么呢,就說說怎么模擬實(shí)現(xiàn)吧。我這里用的是ES6的語法,我只是覺得這樣寫比較簡單但總體思路不變。
下面以這個(gè)為例:

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)用者,并添加一個(gè)方法
    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(重點(diǎn))

// 簡易版
Function.prototype.bindh = function(context){
    let args = [...arguments].slice(1);
    let that = this;
    return function (argument) { // bind返回一個(gè)函數(shù)
        let args2 = [...arguments].slice(0);
        that.call(context, ...args.concat(args2));
    }
}
show.bindh(obj)(5);


但上面bind的方式有一點(diǎn)錯(cuò)誤。我們來看看js里面的bind和我們的在new之后有什么區(qū)別。
上面是js的后面是模擬的。看到了吧。

因?yàn)樵偷脑?,我們來改進(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一直是我們困惑的問題,有時(shí)候能看懂但代碼一多,調(diào)用一多,我們就蒙了,下面我來簡單介紹一下。

在默認(rèn)情況下this指向window(非嚴(yán)格模式)

誰調(diào)用指向誰

call.apply

bind

new

我想到的差不多就這幾種吧,你或許會(huì)發(fā)現(xiàn)其實(shí)是按this綁定的優(yōu)先級(jí)升序排序的。如果你看懂了bind的模擬實(shí)現(xiàn)也許會(huì)知道為什么bind的優(yōu)先級(jí)會(huì)高于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)先級(jí)高,跟綁定順序沒區(qū)別

希望這些菜能滿足您的胃口,但愿也能給您填飽一些肚子。我以后還會(huì)繼續(xù)努力提高自己的廚藝,希望嘗到這個(gè)菜的人都會(huì)喜歡。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/100698.html

相關(guān)文章

  • JS之函數(shù)(1)

    摘要:前言這段時(shí)間突然發(fā)現(xiàn)原生好多東西都忘記了但有些東西確實(shí)很重要所以又重新再梳理一次。 showImg(https://segmentfault.com/img/bVbqqkr?w=874&h=382); 前言 這段時(shí)間突然發(fā)現(xiàn)JS原生好多東西都忘記了,但有些東西確實(shí)很重要,所以又重新再梳理一次。主要有函數(shù)的3種定義方法,ES5函數(shù)this指向,call與appl用法,JS常見的4種設(shè)計(jì)模...

    宋華 評(píng)論0 收藏0
  • 常見js筆試面試題(持續(xù)更新)

    摘要:相當(dāng)于繞過了瀏覽器端,自然就不存在跨域問題。三者的區(qū)別與服務(wù)器的交互數(shù)據(jù)始終在同源的請(qǐng)求中攜帶即使不需要,即在瀏覽器和服務(wù)器間來回傳遞。而和不會(huì)自動(dòng)把數(shù)據(jù)發(fā)給服務(wù)器,僅在本地保存。和雖然也有存儲(chǔ)大小的限制,但比大得多,可以達(dá)到或更大。 本文提供最簡便的解答方式,方便快速記憶,復(fù)盤,詳細(xì)答案可自己再搜一下。 js基礎(chǔ)知識(shí) 1. javascript typeof返會(huì)的數(shù)據(jù)類型有哪些 ob...

    yuxue 評(píng)論0 收藏0
  • 基本方法筆記 - 收藏集 - 掘金

    摘要:探討判斷橫豎屏的最佳實(shí)現(xiàn)前端掘金在移動(dòng)端,判斷橫豎屏的場景并不少見,比如根據(jù)橫豎屏以不同的樣式來適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗(yàn)。 探討判斷橫豎屏的最佳實(shí)現(xiàn) - 前端 - 掘金在移動(dòng)端,判斷橫豎屏的場景并不少見,比如根據(jù)橫豎屏以不同的樣式來適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗(yàn)。 判斷橫豎屏的實(shí)現(xiàn)方法多種多樣,本文就此來探討下目前有哪些實(shí)現(xiàn)方法以及其中的優(yōu)...

    maochunguang 評(píng)論0 收藏0
  • 基于Nuclear的Web組件-Todo的十一種寫法

    摘要:直搗黃龍黃龍即黃龍府,轄地在今吉林一帶,應(yīng)該是指長春市農(nóng)安縣,為金人腹地。一直打到黃龍府。指搗毀敵人的巢穴。有人會(huì)說組合優(yōu)于繼承的。的變更會(huì)自動(dòng)更新依賴的組件??梢圆僮鲗?duì)象實(shí)例,的變更會(huì)自動(dòng)更新組件,屬性設(shè)置方法調(diào)用。 刀耕火種 刀耕火種是新石器時(shí)代殘留的農(nóng)業(yè)經(jīng)營方式。又稱遷移農(nóng)業(yè),為原始生荒耕作制。 var TodoApp = Nuclear.create({ add: f...

    jayce 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<