面試題目
這是 搜狐JavaScript面試題 ,要求如下:
實現一個叫Man的類,包含attr, words, say三個方法。
var Man; // +++++++++++答題區域+++++++++++ // +++++++++++答題結束+++++++++++ try { var me = Man({ fullname: "小紅" }); var she = new Man({ fullname: "小紅" }); console.group(); console.info( "我的名字是:" + me.attr("fullname") + "\n我的性別是:" + me.attr("gender" )); console.groupEnd(); /* ------[執行結果]------ 我的名字是:小紅 我的性別是:<用戶未輸入> ------------------ */ me.attr( "fullname", "小明" ); me.attr( "gender", "男" ); me.fullname = "廢柴" ; me.gender = "人妖" ; she.attr( "gender", "女" ); console.group(); console.info( "我的名字是:" + me.attr("fullname") + "\n我的性別是:" + me.attr("gender" )); console.groupEnd(); /* ------[執行結果]------ 我的名字是:小明 我的性別是:男 ------------------ */ console.group(); console.info( "我的名字是:" + she.attr("fullname") + "\n我的性別是:" + she.attr("gender" )); console.groupEnd(); /* ------[執行結果]------ 我的名字是:小紅 我的性別是:女 ------------------ */ me.attr({ "words-limit": 3 , "words-emote": "微笑" }); me.words( "我喜歡看視頻。" ); me.words( "我們的辦公室太漂亮了。" ); me.words( "視頻里美女真多!" ); me.words( "我平時都看優酷!" ); console.group(); console.log(me.say()); /* ------[執行結果]------ 小明微笑:"我喜歡看視頻。我們的辦公室太漂亮了。視頻里美女真多!" ------------------ */ me.attr({ "words-limit": 2 , "words-emote": "喊" }); console.log(me.say()); console.groupEnd(); /* ------[執行結果]------ 小明喊:"我喜歡看視頻。我們的辦公室太漂亮了。" ------------------ */ } catch (e){ console.error( "執行出錯,錯誤信息: " + e); }
分析過程
分析如下:
從實例化對象的方式看,用new或不用都可以,這是一種作用域安全構造函數,原理就是檢查this是不是指向當前方法本身,如果不是就強制new一個對象出來。所以大體框架如下:
Man= function (obj){ if ( this instanceof arguments.callee){ for ( var e in obj){ this [e]= obj[e]; } } else { return new Man(obj); } };
通過觀察可以發現,attr方法可以獲取或設置屬性值,并且參數可以是一個字符串,一個字符串加一個值,一個對象。所以attr方法定義如下:
Man.prototype.attr= function (attr,val){ if (val){ this [attr]= val; } else { if ( typeof attr === "string" ){ return this .hasOwnProperty(attr)? this [attr]:"<用戶未輸入>" ; } else if ( typeof attr === "object" ){ for ( var e in attr){ this [e]= attr[e]; } } else { } } }
通過觀察words可以發現,這里就是傳入了一些字符串,以便在say方法中調用,所以這里直接給Man添加一個words_limit_arr的數組,用來存放這些字符串,所以words方法實現如下:
Man.prototype.words= function (str){ this .words_limit_arr.push(str); }
最后就是say方法了,通過觀察可以發現,say方法就是把fullname屬性的值加上limit-emote的值,再加上前words-limit個words_limit_arr項連接成的字符串,所以定義如下:
Man.prototype.say= function (){ return this ["fullname"]+ this ["words-emote"]+":"+"\""+ this .words_limit_arr.slice(0, this ["words-limit"]).join("")+"\"" ; }
整個合起來就是:
var Man= function (obj){ if ( this instanceof arguments.callee){ for ( var e in obj){ this [e]= obj[e]; } this .words_limit_arr= []; } else { return new Man(obj); } }; Man.prototype.attr = function (attr,val){ if (val){ this [attr]= val; } else { if ( typeof attr === "string" ){ return this .hasOwnProperty(attr)? this [attr]:"<用戶未輸入>" ; } else if ( typeof attr === "object" ){ for ( var e in attr){ this [e]= attr[e]; } } else { } } } Man.prototype.words = function (str){ this .words_limit_arr.push(str); } Man.prototype.say = function (){ return this ["fullname"]+ this ["words-emote"]+":"+"\""+ this .words_limit_arr.slice(0, this ["words-limit"]).join("")+"\"" ; }
但其中有個問題沒有解決,就是用me.fullname="xxx"方式的賦值不能改變me.attr("fullname","xxx")方式的賦值。這個問題導致運行效果如下:
這個問題要如何解決呢,我一直沒想到,后來參考了別人的代碼,那位朋友的思路是讓me.attr("fullname","xxx")方式對fullname的賦值跟me.fullname不是同一個屬性。
在沒想到其他方案之前,我也只好把我的代碼修改如下:
var Man= function (obj){ if ( this instanceof arguments.callee){ this .infos= { }; for ( var e in obj){ this .infos[e]= obj[e]; } this .words_limit_arr= []; } else { return new Man(obj); } }; Man.prototype.attr = function (attr,val){ if (val){ this .infos[attr]= val; } else { if ( typeof attr === "string" ){ return this .infos[attr]? this .infos[attr]:"<用戶未輸入>" ; } else if ( typeof attr === "object" ){ for ( var e in attr){ this .infos[e]= attr[e]; } } else { } } } Man.prototype.words = function (str){ this .words_limit_arr.push(str); } Man.prototype.say = function (){ return this .infos["fullname"]+ this .infos["words-emote"]+":"+"\""+ this .words_limit_arr.slice(0, this .infos["words-limit"]).join("")+"\"" ; }
修改后運行效果如下:
小結
本面試題主要考查了 作用域安全構造函數,instanceof/typeof 的用法,slice的用法,對數組的遍歷,對對象成員的遍歷等知識點。
關于上面提到的“用me.fullname="xxx"方式的賦值不能改變me.attr("fullname","xxx")方式的賦值”問題,如果各位朋友有新的方案,請不吝指點。也歡迎對我的方案拍磚論討。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
