成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

高級(jí)JS試題

he_xd / 2167人閱讀

摘要:本文是高級(jí)入門的配套試題,題目解析的部分內(nèi)容將引用高級(jí)入門。接收一個(gè)對象,并由這個(gè)對象去調(diào)用函數(shù)。循環(huán)內(nèi),調(diào)用函數(shù),并設(shè)置第二個(gè)參數(shù)的值為。所以相當(dāng)于執(zhí)行而的作用是往消息隊(duì)列中存放一個(gè)回調(diào)函數(shù),并在特定時(shí)間間隔后執(zhí)行它。

本文是JS高級(jí)入門的配套試題,題目解析的部分內(nèi)容將引用JS高級(jí)入門

題目一(this指針)
    function logName(){
        console.log(this.name);
    }
    function doFun1(fn){
        fn();
    }
    function doFun2(o){
        o.logName();
    }
    var obj = {
        name: "LiLei",
        logName: logName
    };
    var name = "HanMeiMei";
    doFun1(obj.logName);
    doFun2(obj);
解析

題目首先定義了三個(gè)函數(shù):
【】logName:打印調(diào)用者(即誰去調(diào)用它,通常是一個(gè)對象)的name屬性。
【】doFun1:接收一個(gè)函數(shù),并直接運(yùn)行這個(gè)函數(shù)。
【】doFun2:接收一個(gè)對象,并由這個(gè)對象去調(diào)用logName函數(shù)。
而后定義了兩個(gè)變量:
【】obj是一個(gè)對象,里面定義了name(假設(shè)另命名為_name)的字符串變量。定義了logName(假設(shè)另起名字為_logName),指向外部的logName函數(shù)。
【】name是一個(gè)字符串變量。
最后分別對兩個(gè)函數(shù)進(jìn)行調(diào)用,
【】doFun1(obj.logName)。

向函數(shù)傳遞了obj對象內(nèi)部的_logName,而_logName是指向logName的。所以實(shí)際上doFun1接收的是指向logName函數(shù)的變量。即等價(jià)于doFun1(logName)。

而在doFun1內(nèi)部是直接執(zhí)行l(wèi)ogName的。沒有明確的調(diào)用者。則這時(shí)等價(jià)于由window對象去調(diào)用,等價(jià)于window.logName。

而再由于所有在全局作用域(注意僅僅是全局作用域)中定義的變量都是window對象下的變量。都可以通過window對象進(jìn)行訪問。
所以這時(shí)訪問到的就是name。

所以輸出的是HanMeiMei。

【】doFun2(obj)。

傳遞給doFun2的是obj的地址值,即doFun2中的o指向的就是obj,等價(jià)于obj。

o.logName是由o去調(diào)用logName。相當(dāng)于obj.logName。

所以找到的是obj內(nèi)部的name(即我們假定的_name)。

所以打印出的是LiLei。

答案
HanMeiMei
LiLei
題目二(this指針的修改apply)
    function fun(somthing) {
        console.log(this.name, somthing);
    }
    function bindFun(fn, obj) {
        return function () {
            return fn.apply(obj, arguments);
        }
    }
    var obj = {
        name: "LiLei"
    };
    var bar = bindFun(fun, obj);
    var b = bar("HanMeiMei");
    console.log(b);
解析

本題的主要考點(diǎn)是this的相關(guān)函數(shù)apply。
首先定義了三個(gè)函數(shù):
【】fun函數(shù):接收變量,并且打印這個(gè)函數(shù)的調(diào)用者的name值,以及形參something。
【】bindFun函數(shù):接收兩個(gè)參數(shù),分別是函數(shù)以及對象。bindFun沒有邏輯操作。只是返回了一個(gè)匿名函數(shù)(我們假定為_fun)
【】_fun函數(shù):同樣沒有操作,直接返回一個(gè)已經(jīng)通過apply修改了this的函數(shù)的執(zhí)行結(jié)果。(即直接返回一個(gè)函數(shù)執(zhí)行結(jié)果值,而這個(gè)函數(shù)的this的值是已經(jīng)被修改過的)
而后定義了三個(gè)變量:
【】obj是一個(gè)對象,里面只定義了name字符串變量。
【】bar是一個(gè)變量,這個(gè)變量的值為bindFun函數(shù)執(zhí)行的結(jié)果值。
【】b是一個(gè)變量,值為bar函數(shù)執(zhí)行的結(jié)果值。
整段代碼中,除了定義,一共只執(zhí)行了3句邏輯語句:
【】在bindFun函數(shù)的執(zhí)行,傳遞了兩個(gè)函數(shù),分別是fun函數(shù),obj對象。bindFun函數(shù)執(zhí)行結(jié)果是返回一個(gè)函數(shù)_fun。所以bar指向_fun函數(shù)。
【】bar函數(shù)的調(diào)用,即相當(dāng)于_fun函數(shù)的調(diào)用。

_fun函數(shù)的返回fn.apply(obj, arguments)的運(yùn)行值;

其中這里的fn是bindFun函數(shù)接受的第一個(gè)參數(shù)fun,即返回的是fun函數(shù)。

而這個(gè)fun函數(shù)進(jìn)行了apply的函數(shù)調(diào)用,修改了函數(shù)中this的值。

this指向?yàn)閎indFun函數(shù)的第二個(gè)參數(shù)值,即外部的obj變量。

apply函數(shù)還接受了第二個(gè)參數(shù)arguments,即_fun函數(shù)的參數(shù)數(shù)組。即bar函數(shù)的參數(shù)數(shù)組【"HanMeiMei"】。作為fun函數(shù)的參數(shù)。

apply函數(shù)的作用是馬上執(zhí)行調(diào)用者函數(shù),即馬上執(zhí)行bar(即_fun,即fun)函數(shù)。

fun函數(shù)執(zhí)行是打印this.name,和參數(shù)something。this指向obj,所以this.name為LiLei。而something值為【"HanMeiMei"】

所以打印了,LiLeiHanMeiMei。并且沒有返回值。

【】b是bar函數(shù)的返回值,然而bar函數(shù)并沒有返回東西,所以是undefined。所以console.log(b)打印的值是undefined。

繞了一圈,整個(gè)過程相當(dāng)于執(zhí)行。fun.call(obj,"HanMeiMei");

答案
LiLeiHanMeiMei
undefined
題目三(自執(zhí)行函數(shù))
function logName() {
    console.log(this);
    console.log(this.name);
}
var name = "XiaoMing";
var LiLei = { name: "LiLei", logName: logName };
var HanMeiMei = { name: "HanMeiMei" };
(HanMeiMei.logName = LiLei.logName)();
解析

這題相對簡單一些。只考到自執(zhí)行函數(shù)的定義。并沒有借助他的特性做代碼隔離。只是想考一下是否已經(jīng)掌握了自執(zhí)行函數(shù)的定義。
首先定義了一個(gè)函數(shù):
【】logName,打印出調(diào)用者(即this指針的指向),已經(jīng)調(diào)用者的name屬性值
而后定義了三個(gè)變量:
【】name:字符串變量,由于全局的,所以相當(dāng)于window對象的屬性值。
【】LiLei:定義了對象,該對象包含name值,以及l(fā)ogName(我們假定LiLei的logName重新命名為_logName)。指向外部的logName函數(shù)
【】HanMeiMei:定義了對象,該對象只包含name值。
最終只執(zhí)行了一條語句,兩個(gè)步驟。
分別是賦值語句:

為HanMeiMei對象添加一個(gè)參數(shù)logName,賦值為LiLei的_logName。即指向外部的logName。這不是重點(diǎn),重點(diǎn)是賦值語句的結(jié)果是什么?
是所賦的值,即賦值語句的結(jié)果是LiLei.logName,即HanMeiMei.logName = LiLei.logName終止得到的是logName。

然后對這個(gè)函數(shù)進(jìn)行調(diào)用。即logName(),這時(shí)this沒有發(fā)生改變,還是window,所以輸出是打印window對象。已經(jīng)window.name即XiaoMing。

答案
XiaoMing
題目四(聲明提前)
    test();
    var test = 0;
    function test() {
        console.log(1);
    }
    test();
    test = function () {
        console.log(2);
    };
    test();
解析

聲明提前的題,把背后的代碼執(zhí)行順序理順就好。

首先將聲明都放到代碼的最上面:

var test;//定義變量

function test(){console.log(1)}//定義函數(shù)

然后執(zhí)行的操作:

test();//函數(shù)調(diào)用操作

test = 0;//賦值操作

test();//函數(shù)調(diào)用操作

test = function(){console.log(2)}//賦值操作,將test賦值為函數(shù)

test();//函數(shù)調(diào)用操作

所以上述代碼等價(jià)于(聲明提前,先定義,后執(zhí)行):

var test;

function test(){console.log(1)}

test();//調(diào)用函數(shù),輸出1

test = 0;

test();//此時(shí)test為0,不是函數(shù),將報(bào)錯(cuò)test is not a function

test = function(){console.log(2)}//由于JS報(bào)錯(cuò),后面的代碼將不被運(yùn)行

test();//由于JS報(bào)錯(cuò),后面的代碼將不被運(yùn)行

綜合來說,這里設(shè)置了三個(gè)考點(diǎn):

聲明提前。

函數(shù)的定義與函數(shù)賦值的區(qū)別,function xx為函數(shù)定義,將整體上移。

JS報(bào)錯(cuò)后,后面的代碼將不被運(yùn)行。

答案
1
Uncaught TypeError: test is not a function
題目五(基本類型與引用類型)
    var name = "LiLei";
    var people = {name: "HanMeiMei"};
    function test1(name) {
        name = "LaoWang";
    }
    function test2(obj) {
        obj.name = "LaoWang";
    }
    test1(name);
    test2(people);
    console.log("name    " + name);
    console.log("name    " + people.name);
解析

題目首先定義了兩個(gè)函數(shù):
【】test1:接受一個(gè)參數(shù),并修改該參數(shù)的值。
【】test2:接收一個(gè)對象,并修改該對象的屬性的值。
而后定義了兩個(gè)變量:
【】name是一個(gè)字符串參數(shù),值為"LiLei"
【】people是一個(gè)對象,包含一個(gè)name屬性。值為"HanMeiMei"
然后分別對兩個(gè)函數(shù)進(jìn)行調(diào)用:
test1(name):即將name作為參數(shù),調(diào)用test1函數(shù)。

這時(shí)函數(shù)的內(nèi)部將產(chǎn)生一個(gè)新的參數(shù)name(記作_name),它的值等于外部的name的值(LiLei);

test1函數(shù)將_name的值修改為"LaoWang",但是由于_name和name是兩份獨(dú)立的變量。所以name的值不受改變。

test2(people):將people作為參數(shù),調(diào)用test1函數(shù)。

這時(shí)函數(shù)的內(nèi)部將產(chǎn)生一個(gè)新的參數(shù)obj,它的值等于外部的people的值;

而people是引用類型,其值為對象{name:"HanMeiMei"}的地址值。所以obj也為對象{name:"HanMeiMei"}的地址值。

test2對對象{name:"HanMeiMei"}的name屬性進(jìn)行修改,改為"LaoWang"
所以obj和people的name值都發(fā)生了改變。

這里涉及到兩個(gè)知識(shí)點(diǎn)

基本數(shù)據(jù)類型是按值訪問的,即該變量就存在了實(shí)際值。而引用數(shù)據(jù)類型保存的是則是對實(shí)際值的引用(即指向?qū)嶋H值的指針)。

函數(shù)形參(即在函數(shù)中實(shí)際使用的值,如test函數(shù)里面的name)和參數(shù)的實(shí)參(即往調(diào)用函數(shù)時(shí)調(diào)用的參數(shù),如test(name)中的name)的值相同,但并不是"同一個(gè)值"(在內(nèi)存中的地址是不同的,相當(dāng)于var a = b =0;)。

在函數(shù)參數(shù)的傳遞,是通過按值傳遞的。

答案
LiLei
LaoWang
題目六(JS線程與閉包)
    執(zhí)行的結(jié)果是什么,分別在什么時(shí)間輸出
    for (var i = 1; i < 5; i++) {
        setTimeout(function () {
            console.log(i);
        }, i * 1000);
     }
解析

JS線程的規(guī)則:程序?qū)⑾劝阎鬟壿嫷膬?nèi)容做完,再去讀取消息列表,調(diào)用消息列表中的回調(diào)函數(shù)

在這里主邏輯為一個(gè)for循環(huán),從i為1到i為4循環(huán)執(zhí)行4次for循環(huán)的內(nèi)容。

for循環(huán)內(nèi),調(diào)用setTimeout函數(shù),并設(shè)置第二個(gè)參數(shù)的值為i。注意這里是對setTimeout函數(shù)直接進(jìn)行調(diào)用。所以參數(shù)中i的值是隨for循環(huán)改變的。所以相當(dāng)于執(zhí)行

setTimeout(function () {doSomething}, 1000);

setTimeout(function () {doSomething}, 2000);

setTimeout(function () {doSomething}, 3000);

setTimeout(function () {doSomething}, 4000);

而setTimeout的作用是往消息隊(duì)列中存放一個(gè)回調(diào)函數(shù),并在特定時(shí)間間隔后執(zhí)行它。所以該回調(diào)函數(shù)會(huì)在for循環(huán)之后完成。

for循環(huán)執(zhí)行完時(shí),i的值為5。(因?yàn)?<5不成立,結(jié)束循環(huán))。所以調(diào)用回調(diào)函數(shù)function(){console.log(i)}時(shí),i的值為5。所以輸出為5。

閉包是因?yàn)榛卣{(diào)函數(shù)引用到了for循環(huán)的i,回調(diào)函數(shù)沒執(zhí)行完,i不能被回收。所以還是能訪問到。

答案
輸出4次,每一秒輸出一個(gè)5
題目七(作用域陷阱)
    function logName(){
        console.log(name);
    }
    function test () {
        var name = 3;
        logName();
    }
    var name = 2;
    test();
解析

一句話可以解釋完:作用域的層級(jí)關(guān)系與函數(shù)定義時(shí)所處的層級(jí)關(guān)系相同
注意是,函數(shù)定義時(shí)的層級(jí)關(guān)系,而不是調(diào)用時(shí)的層級(jí)關(guān)系。
在這里,logName函數(shù),test函數(shù)以及外部的name變量(值為2)處于同一個(gè)層級(jí)。
所以調(diào)用logName時(shí),找到的是外部的name變量。
所以打印出2

答案
2
題目八(隱式閉包)
    function logNum(num) {
        console.log("num   " + num);
    }
    for (var i = 0; i < 2; i++) {
        var fun = logNum.bind(null, i);
        setTimeout(fun, 100);
    }
解析

這道題和第六題很像,但是運(yùn)行結(jié)果并不一樣。
原因是bind函數(shù)產(chǎn)生了隱式閉包。
為什么bind函數(shù)能修改this指針?底層實(shí)現(xiàn)筆者不知道,但是我們可以利用閉包的特性通過自執(zhí)行函數(shù)來模擬bind函數(shù)。
bind(obj,elem0,elem1,elem2...)函數(shù)相當(dāng)于

(function(_obj,_elem0,_elem1,_elem2...){
    return function(){//這個(gè)函數(shù)就是調(diào)用bind函數(shù)的函數(shù)
        doSomething;
        //將this.替換成_obj.
        //這里將可能使用到_elem0,_elem1,_elem2參數(shù)。
    }
})(obj,elem0,elem1,elem2...)

通過自執(zhí)行函數(shù)返回一個(gè)函數(shù),形成一個(gè)閉包,內(nèi)部函數(shù)調(diào)用的參數(shù)是自執(zhí)行函數(shù)的參數(shù),而不是外部的元素。

根據(jù)前面第五題的解析函數(shù)形參(即在函數(shù)中實(shí)際使用的值,如test函數(shù)里面的name)和參數(shù)的實(shí)參(即往調(diào)用函數(shù)時(shí)調(diào)用的參數(shù),如test(name)中的name)的值相同,但并不是"同一個(gè)值"(在內(nèi)存中的地址是不同的,相當(dāng)于var a = b =0;)。
doSomething中使用到的參數(shù)是自執(zhí)行函數(shù)的形參(_elemX),而不是外部的實(shí)參elem。
所以外部的elem的變化對doSomething沒有影響。

根據(jù)解析,對題目進(jìn)行改造,相當(dāng)于

function logNum(num) {
    console.log("num   " + num);
}
for (var i = 0; i < 2; i++) {
    var fun = (function(_i){
        return function(){
            console.log(_i);
        }
    })(i);
    setTimeout(fun, 100);
}

而自執(zhí)行函數(shù)是定義完馬上執(zhí)行的。所以拿到的值_i也是隨著for循環(huán)改變的。
所以輸出0 1

利用該特性還可以解決常見的面試題:通過原生JS返回所點(diǎn)擊元素索引值。

    var domList = document.getElementsByTagName("div");
    for (var i = 0, length = domList.length; i < length; i++) {
        var item = domList[ i ];
        (function(_item, _i) {
            _item.addEventListener("click", function() {
                console.log(_i);
            })
        })(item, i)
    }
答案
0
1

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/81869.html

相關(guān)文章

  • 面試試題總結(jié)

    摘要:閑心面試題一任選一題分的區(qū)別的區(qū)別是無序列表,是有序列表,是定義列表有層次關(guān)系。無任何語義,僅僅用作樣式化或者腳本化的鉤子是有一定語義的,適合有主題性的內(nèi)容,表示一個(gè)專題,一般有標(biāo)題,但是不可以亂用。誕生于年,由等人創(chuàng)建,后為所收購。 閑心面試題 一、任選一題(5分)a) ul、ol、dl的區(qū)別?b) div、section、article的區(qū)別? a:ul是無序列表,ol是有序列表,...

    alaege 評(píng)論0 收藏0
  • 前端必須要珍藏的技術(shù)文章和面試題

    摘要:前端工程師學(xué)習(xí)資料,快速查找面試題,經(jīng)典技術(shù)文章的總結(jié),編程技巧,幫助學(xué)習(xí)者快速定位問題花點(diǎn)時(shí)間整理出一下前端工程師日常工作所需要的學(xué)習(xí)資料查找,幫助學(xué)習(xí)者快速掌握前端工程師開發(fā)的基本知識(shí)編程始于足下記住再牛逼的夢想也抵不住傻逼似的堅(jiān)持蝴蝶 前端工程師學(xué)習(xí)資料,快速查找面試題,經(jīng)典技術(shù)文章的總結(jié),編程技巧,幫助學(xué)習(xí)者快速定位問題花點(diǎn)時(shí)間整理出一下web前端工程師日常工作所需要的學(xué)習(xí)資料...

    MoAir 評(píng)論0 收藏0
  • 高級(jí)前端面試題大匯總(只有試題,沒有答案)

    摘要:面試題來源于網(wǎng)絡(luò),看一下高級(jí)前端的面試題,可以知道自己和高級(jí)前端的差距。 面試題來源于網(wǎng)絡(luò),看一下高級(jí)前端的面試題,可以知道自己和高級(jí)前端的差距。有些面試題會(huì)重復(fù)。 使用過的koa2中間件 koa-body原理 介紹自己寫過的中間件 有沒有涉及到Cluster 介紹pm2 master掛了的話pm2怎么處理 如何和MySQL進(jìn)行通信 React聲明周期及自己的理解 如何...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<