摘要:第一種直接調(diào)用避免在不必要的情況下使用,是一個(gè)危險(xiǎn)的函數(shù),他執(zhí)行的代碼擁有著執(zhí)行者的權(quán)利。來自于此外,實(shí)現(xiàn)需要考慮實(shí)例化后對(duì)原型鏈的影響。函數(shù)柯里化的主要作用和特點(diǎn)就是參數(shù)復(fù)用提前返回和延遲執(zhí)行。
手寫路徑導(dǎo)航
實(shí)現(xiàn)一個(gè)new操作符
實(shí)現(xiàn)一個(gè)JSON.stringify
實(shí)現(xiàn)一個(gè)JSON.parse
實(shí)現(xiàn)一個(gè)call或 apply
實(shí)現(xiàn)一個(gè)Function.bind
實(shí)現(xiàn)一個(gè)繼承
實(shí)現(xiàn)一個(gè)JS函數(shù)柯里化
手寫一個(gè)Promise(中高級(jí)必考)
手寫防抖(Debouncing)和節(jié)流(Throttling)
手寫一個(gè)JS深拷貝
實(shí)現(xiàn)一個(gè)instanceOf
1. 實(shí)現(xiàn)一個(gè)new操作符來源:「你不知道的javascript」 英文版
new操作符做了這些事:
它創(chuàng)建了一個(gè)全新的對(duì)象。
它會(huì)被執(zhí)行[[Prototype]](也就是__proto__)鏈接。
它使this指向新創(chuàng)建的對(duì)象。。
通過new創(chuàng)建的每個(gè)對(duì)象將最終被[[Prototype]]鏈接到這個(gè)函數(shù)的prototype對(duì)象上。
如果函數(shù)沒有返回對(duì)象類型Object(包含Functoin, Array, Date, RegExg, Error),那么new表達(dá)式中的函數(shù)調(diào)用將返回該對(duì)象引用。
function New(func) {
var res = {};
if (func.prototype !== null) {
res.__proto__ = func.prototype;
}
var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
return ret;
}
return res;
}
var obj = New(A, 1, 2);
// equals to
var obj = new A(1, 2);
2. 實(shí)現(xiàn)一個(gè)JSON.stringify
JSON.stringify(value[, replacer [, space]]):
Boolean | Number| String 類型會(huì)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的原始值。
undefined、任意函數(shù)以及symbol,會(huì)被忽略(出現(xiàn)在非數(shù)組對(duì)象的屬性值中時(shí)),或者被轉(zhuǎn)換成 null(出現(xiàn)在數(shù)組中時(shí))。
不可枚舉的屬性會(huì)被忽略
如果一個(gè)對(duì)象的屬性值通過某種間接的方式指回該對(duì)象本身,即循環(huán)引用,屬性也會(huì)被忽略。
function jsonStringify(obj) {
let type = typeof obj;
if (type !== "object") {
if (/string|undefined|function/.test(type)) {
obj = """ + obj + """;
}
return String(obj);
} else {
let json = []
let arr = Array.isArray(obj)
for (let k in obj) {
let v = obj[k];
let type = typeof v;
if (/string|undefined|function/.test(type)) {
v = """ + v + """;
} else if (type === "object") {
v = jsonStringify(v);
}
json.push((arr ");"" : """ + k + "":") + String(v));
}
return (arr ");"[" : "{") + String(json) + (arr ");"]" : "}")
}
}
jsonStringify({x : 5}) // "{"x":5}"
jsonStringify([1, "false", false]) // "[1,"false",false]"
jsonStringify({b: undefined}) // "{"b":"undefined"}"
3. 實(shí)現(xiàn)一個(gè)JSON.parse
JSON.parse(text[, reviver])
用來解析JSON字符串,構(gòu)造由字符串描述的JavaScript值或?qū)ο?。提供可選的reviver函數(shù)用以在返回之前對(duì)所得到的對(duì)象執(zhí)行變換(操作)。
3.1 第一種:直接調(diào)用 evalfunction jsonParse(opt) {
return eval("(" + opt + ")");
}
jsonParse(jsonStringify({x : 5}))
// Object { x: 5}
jsonParse(jsonStringify([1, "false", false]))
// [1, "false", falsr]
jsonParse(jsonStringify({b: undefined}))
// Object { b: "undefined"}
避免在不必要的情況下使用 eval,eval() 是一個(gè)危險(xiǎn)的函數(shù), 他執(zhí)行的代碼擁有著執(zhí)行者的權(quán)利。如果你用 eval()運(yùn)行的字符串代碼被惡意方(不懷好意的人)操控修改,您最終可能會(huì)在您的網(wǎng)頁(yè)/擴(kuò)展程序的權(quán)限下,在用戶計(jì)算機(jī)上運(yùn)行惡意代碼。
它會(huì)執(zhí)行JS代碼,有XSS漏洞。
如果你只想記這個(gè)方法,就得對(duì)參數(shù)json做校驗(yàn)。
var rx_one = /^[],:{}s]*$/;
var rx_two = /(");"/bfnrt]|u[0-9a-fA-F]{4})/g;
var rx_three = /"[^"
]*"|true|false|null|-");if (
rx_one.test(
json
.replace(rx_two, "@")
.replace(rx_three, "]")
.replace(rx_four, "")
)
) {
var obj = eval("(" +json + ")");
}
3.2 第二種:Function
來源 神奇的eval()與new Function()
核心:Function與eval有相同的字符串參數(shù)特性。
var func = new Function(arg1, arg2, ..., functionBody);
在轉(zhuǎn)換JSON的實(shí)際應(yīng)用中,只需要這么做。
var jsonStr = "{ "age": 20, "name": "jack" }"
var json = (new Function("return " + jsonStr))();
eval 與 Function 都有著動(dòng)態(tài)編譯js代碼的作用,但是在實(shí)際的編程中并不推薦使用。
這里是面向面試編程,寫這兩種就夠了。至于第三,第四種,涉及到繁瑣的遞歸和狀態(tài)機(jī)相關(guān)原理,具體可以看:
4. 實(shí)現(xiàn)一個(gè)call或 apply《JSON.parse 三種實(shí)現(xiàn)方式》
實(shí)現(xiàn)改編來源:JavaScript深入之call和apply的模擬實(shí)現(xiàn) #11
call語法:
fun.call(thisArg, arg1, arg2, ...),調(diào)用一個(gè)函數(shù), 其具有一個(gè)指定的this值和分別地提供的參數(shù)(參數(shù)的列表)。
apply語法:
4.1 Function.call按套路實(shí)現(xiàn)func.apply(thisArg, [argsArray]),調(diào)用一個(gè)函數(shù),以及作為一個(gè)數(shù)組(或類似數(shù)組對(duì)象)提供的參數(shù)。
call核心:
將函數(shù)設(shè)為對(duì)象的屬性
執(zhí)行&刪除這個(gè)函數(shù)
指定this到函數(shù)并傳入給定參數(shù)執(zhí)行函數(shù)
如果不傳入?yún)?shù),默認(rèn)指向?yàn)?window
為啥說是套路實(shí)現(xiàn)呢?因?yàn)檎鎸?shí)面試中,面試官很喜歡讓你逐步地往深考慮,這時(shí)候你可以反套路他,先寫個(gè)簡(jiǎn)單版的:
4.1.1 簡(jiǎn)單版var foo = {
value: 1,
bar: function() {
console.log(this.value)
}
}
foo.bar() // 1
4.1.2 完善版
當(dāng)面試官有進(jìn)一步的發(fā)問,或者此時(shí)你可以假裝思考一下。然后寫出以下版本:
Function.prototype.call2 = function(content = window) {
content.fn = this;
let args = [...arguments].slice(1);
let result = content.fn(...args);
delete content.fn;
return result;
}
let foo = {
value: 1
}
function bar(name, age) {
console.log(name)
console.log(age)
console.log(this.value);
}
bar.call2(foo, "black", "18") // black 18 1
4.2 Function.apply的模擬實(shí)現(xiàn)
apply()的實(shí)現(xiàn)和call()類似,只是參數(shù)形式不同。直接貼代碼吧:
Function.prototype.apply2 = function(context = window) {
context.fn = this
let result;
// 判斷是否有第二個(gè)參數(shù)
if(arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
5. 實(shí)現(xiàn)一個(gè)Function.bind()
bind()方法:
會(huì)創(chuàng)建一個(gè)新函數(shù)。當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),bind() 的第一個(gè)參數(shù)將作為它運(yùn)行時(shí)的 this,之后的一序列參數(shù)將會(huì)在傳遞的實(shí)參前傳入作為它的參數(shù)。(來自于 MDN )
此外,bind實(shí)現(xiàn)需要考慮實(shí)例化后對(duì)原型鏈的影響。
Function.prototype.bind2 = function(content) {
if(typeof this != "function") {
throw Error("not a function")
}
// 若沒問參數(shù)類型則從這開始寫
let fn = this;
let args = [...arguments].slice(1);
let resFn = function() {
return fn.apply(this instanceof resFn ");function tmp() {}
tmp.prototype = this.prototype;
resFn.prototype = new tmp();
return resFn;
}
6. 實(shí)現(xiàn)一個(gè)繼承
寄生組合式繼承
一般只建議寫這種,因?yàn)槠渌绞降睦^承會(huì)在一次實(shí)例中調(diào)用兩次父類的構(gòu)造函數(shù)或有其它缺點(diǎn)。
核心實(shí)現(xiàn)是:用一個(gè) F 空的構(gòu)造函數(shù)去取代執(zhí)行了 Parent 這個(gè)構(gòu)造函數(shù)。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log("parent name:", this.name);
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
function create(proto) {
function F(){}
F.prototype = proto;
return new F();
}
Child.prototype = create(Parent.prototype);
Child.prototype.sayName = function() {
console.log("child name:", this.name);
}
Child.prototype.constructor = Child;
var parent = new Parent("father");
parent.sayName(); // parent name: father
var child = new Child("son", "father");
7. 實(shí)現(xiàn)一個(gè)JS函數(shù)柯里化
在計(jì)算機(jī)科學(xué)中,柯里化(Currying)是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。
函數(shù)柯里化的主要作用和特點(diǎn)就是參數(shù)復(fù)用、提前返回和延遲執(zhí)行。
7.1 通用版function curry(fn, args) {
var length = fn.length;
var args = args || [];
return function(){
newArgs = args.concat(Array.prototype.slice.call(arguments));
if (newArgs.length < length) {
return curry.call(this,fn,newArgs);
}else{
return fn.apply(this,newArgs);
}
}
}
function multiFn(a, b, c) {
return a * b * c;
}
var multi = curry(multiFn);
multi(2)(3)(4);
multi(2,3,4);
multi(2)(3,4);
multi(2,3)(4);
7.2 ES6騷寫法
const curry = (fn, arr = []) => (...args) => ( arg => arg.length === fn.length ");let curryTest=curry((a,b,c,d)=>a+b+c+d) curryTest(1,2,3)(4) //返回10 curryTest(1,2)(4)(3) //返回10 curryTest(1,2)(3,4) //返回108. 手寫一個(gè)Promise(中高級(jí)必考)
我們來過一遍Promise/A+規(guī)范:
三種狀態(tài)pending| fulfilled(resolved) | rejected
當(dāng)處于pending狀態(tài)的時(shí)候,可以轉(zhuǎn)移到fulfilled(resolved)或者rejected狀態(tài)
當(dāng)處于fulfilled(resolved)狀態(tài)或者rejected狀態(tài)的時(shí)候,就不可變。
必須有一個(gè)then異步執(zhí)行方法,then接受兩個(gè)參數(shù)且必須返回一個(gè)promise:
// onFulfilled 用來接收promise成功的值 // onRejected 用來接收promise失敗的原因 promise1=promise.then(onFulfilled, onRejected);8.1 Promise的流程圖分析
var promise = new Promise((resolve,reject) => {
if (操作成功) {
resolve(value)
} else {
reject(error)
}
})
promise.then(function (value) {
// success
},function (value) {
// failure
})
8.2 面試夠用版
來源:實(shí)現(xiàn)一個(gè)完美符合Promise/A+規(guī)范的Promise
function myPromise(constructor){
let self=this;
self.status="pending" //定義狀態(tài)改變前的初始狀態(tài)
self.value=undefined;//定義狀態(tài)為resolved的時(shí)候的狀態(tài)
self.reason=undefined;//定義狀態(tài)為rejected的時(shí)候的狀態(tài)
function resolve(value){
//兩個(gè)==="pending",保證了狀態(tài)的改變是不可逆的
if(self.status==="pending"){
self.value=value;
self.status="resolved";
}
}
function reject(reason){
//兩個(gè)==="pending",保證了狀態(tài)的改變是不可逆的
if(self.status==="pending"){
self.reason=reason;
self.status="rejected";
}
}
//捕獲構(gòu)造異常
try{
constructor(resolve,reject);
}catch(e){
reject(e);
}
}
同時(shí),需要在myPromise的原型上定義鏈?zhǔn)秸{(diào)用的then方法:
myPromise.prototype.then=function(onFullfilled,onRejected){
let self=this;
switch(self.status){
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
}
測(cè)試一下:
var p=new myPromise(function(resolve,reject){resolve(1)});
p.then(function(x){console.log(x)})
//輸出1
8.3 大廠專供版
直接貼出來吧,這個(gè)版本還算好理解
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function Promise(excutor) {
let that = this; // 緩存當(dāng)前promise實(shí)例對(duì)象
that.status = PENDING; // 初始狀態(tài)
that.value = undefined; // fulfilled狀態(tài)時(shí) 返回的信息
that.reason = undefined; // rejected狀態(tài)時(shí) 拒絕的原因
that.onFulfilledCallbacks = []; // 存儲(chǔ)fulfilled狀態(tài)對(duì)應(yīng)的onFulfilled函數(shù)
that.onRejectedCallbacks = []; // 存儲(chǔ)rejected狀態(tài)對(duì)應(yīng)的onRejected函數(shù)
function resolve(value) { // value成功態(tài)時(shí)接收的終值
if(value instanceof Promise) {
return value.then(resolve, reject);
}
// 實(shí)踐中要確保 onFulfilled 和 onRejected 方法異步執(zhí)行,且應(yīng)該在 then 方法被調(diào)用的那一輪事件循環(huán)之后的新執(zhí)行棧中執(zhí)行。
setTimeout(() => {
// 調(diào)用resolve 回調(diào)對(duì)應(yīng)onFulfilled函數(shù)
if (that.status === PENDING) {
// 只能由pending狀態(tài) => fulfilled狀態(tài) (避免調(diào)用多次resolve reject)
that.status = FULFILLED;
that.value = value;
that.onFulfilledCallbacks.forEach(cb => cb(that.value));
}
});
}
function reject(reason) { // reason失敗態(tài)時(shí)接收的拒因
setTimeout(() => {
// 調(diào)用reject 回調(diào)對(duì)應(yīng)onRejected函數(shù)
if (that.status === PENDING) {
// 只能由pending狀態(tài) => rejected狀態(tài) (避免調(diào)用多次resolve reject)
that.status = REJECTED;
that.reason = reason;
that.onRejectedCallbacks.forEach(cb => cb(that.reason));
}
});
}
// 捕獲在excutor執(zhí)行器中拋出的異常
// new Promise((resolve, reject) => {
// throw new Error("error in excutor")
// })
try {
excutor(resolve, reject);
} catch (e) {
reject(e);
}
}
Promise.prototype.then = function(onFulfilled, onRejected) {
const that = this;
let newPromise;
// 處理參數(shù)默認(rèn)值 保證參數(shù)后續(xù)能夠繼續(xù)執(zhí)行
onFulfilled =
typeof onFulfilled === "function" ");"function" ");if (that.status === FULFILLED) { // 成功態(tài)
return newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try{
let x = onFulfilled(that.value);
resolvePromise(newPromise, x, resolve, reject); // 新的promise resolve 上一個(gè)onFulfilled的返回值
} catch(e) {
reject(e); // 捕獲前面onFulfilled中拋出的異常 then(onFulfilled, onRejected);
}
});
})
}
if (that.status === REJECTED) { // 失敗態(tài)
return newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(that.reason);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
});
}
if (that.status === PENDING) { // 等待態(tài)
// 當(dāng)異步調(diào)用resolve/rejected時(shí) 將onFulfilled/onRejected收集暫存到集合中
return newPromise = new Promise((resolve, reject) => {
that.onFulfilledCallbacks.push((value) => {
try {
let x = onFulfilled(value);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
that.onRejectedCallbacks.push((reason) => {
try {
let x = onRejected(reason);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
});
}
};
9. 手寫防抖(Debouncing)和節(jié)流(Throttling)
9.1 防抖(Debouncing)實(shí)現(xiàn)scroll 事件本身會(huì)觸發(fā)頁(yè)面的重新渲染,同時(shí) scroll 事件的 handler 又會(huì)被高頻度的觸發(fā), 因此事件的 handler 內(nèi)部不應(yīng)該有復(fù)雜操作,例如 DOM 操作就不應(yīng)該放在事件處理中。 針對(duì)此類高頻度觸發(fā)事件問題(例如頁(yè)面 scroll ,屏幕 resize,監(jiān)聽用戶輸入等),有兩種常用的解決方法,防抖和節(jié)流。
典型例子:限制 鼠標(biāo)連擊 觸發(fā)。
一個(gè)比較好的解釋是:
當(dāng)一次事件發(fā)生后,事件處理器要等一定閾值的時(shí)間,如果這段時(shí)間過去后 再也沒有 事件發(fā)生,就處理最后一次發(fā)生的事件。假設(shè)還差 0.01 秒就到達(dá)指定時(shí)間,這時(shí)又來了一個(gè)事件,那么之前的等待作廢,需要重新再等待指定時(shí)間。
// 防抖動(dòng)函數(shù)
function debounce(fn,wait=50,immediate) {
let timer;
return function() {
if(immediate) {
fn.apply(this,arguments)
}
if(timer) clearTimeout(timer)
timer = setTimeout(()=> {
fn.apply(this,arguments)
},wait)
}
}
結(jié)合實(shí)例:滾動(dòng)防抖
// 簡(jiǎn)單的防抖動(dòng)函數(shù)
// 實(shí)際想綁定在 scroll 事件上的 handler
function realFunc(){
console.log("Success");
}
// 采用了防抖動(dòng)
window.addEventListener("scroll",debounce(realFunc,500));
// 沒采用防抖動(dòng)
window.addEventListener("scroll",realFunc);
9.2 節(jié)流(Throttling)實(shí)現(xiàn)
可以理解為事件在一個(gè)管道中傳輸,加上這個(gè)節(jié)流閥以后,事件的流速就會(huì)減慢。實(shí)際上這個(gè)函數(shù)的作用就是如此,它可以將一個(gè)函數(shù)的調(diào)用頻率限制在一定閾值內(nèi),例如 1s,那么 1s 內(nèi)這個(gè)函數(shù)一定不會(huì)被調(diào)用兩次
簡(jiǎn)單的節(jié)流函數(shù):
function throttle(fn, wait) {
let prev = new Date();
return function() {
const args = arguments;
const now = new Date();
if (now - prev > wait) {
fn.apply(this, args);
prev = new Date();
}
}
9.3 結(jié)合實(shí)踐
通過第三個(gè)參數(shù)來切換模式。
const throttle = function(fn, delay, isDebounce) {
let timer
let lastCall = 0
return function (...args) {
if (isDebounce) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn(...args)
}, delay)
} else {
const now = new Date().getTime()
if (now - lastCall < delay) return
lastCall = now
fn(...args)
}
}
}
10. 手寫一個(gè)JS深拷貝
有個(gè)最著名的乞丐版實(shí)現(xiàn),在《你不知道的JavaScript(上)》里也有提及:
10.1 乞丐版
var newObj = JSON.parse( JSON.stringify( someObj ) );10.2 面試夠用版
function deepCopy(obj){
//判斷是否是簡(jiǎn)單數(shù)據(jù)類型,
if(typeof obj == "object"){
//復(fù)雜數(shù)據(jù)類型
var result = obj.constructor == Array ");for(let i in obj){
result[i] = typeof obj[i] == "object" ");else {
//簡(jiǎn)單數(shù)據(jù)類型 直接 == 賦值
var result = obj;
}
return result;
}
關(guān)于深拷貝的討論天天有,這里就貼兩種吧,畢竟我...
11.實(shí)現(xiàn)一個(gè)instanceOf
function instanceOf(left,right) {
let proto = left.__proto__;
let prototype = right.prototype
while(true) {
if(proto === null) return false
if(proto === prototype) return true
proto = proto.__proto__;
}
}
求一份深圳的內(nèi)推
目前本人在準(zhǔn)備跳槽,希望各位大佬和HR小姐姐可以內(nèi)推一份靠譜的深圳前端崗位!996.ICU 就算了。
微信:huab119
郵箱:454274033@qq.com
作者掘金文章總集「多圖警告」重學(xué) TCP/IP 協(xié)議
「Vue實(shí)踐」5分鐘擼一個(gè)Vue CLI 插件
「Vue實(shí)踐」武裝你的前端項(xiàng)目
「中高級(jí)前端面試」JavaScript手寫代碼無敵秘籍
「從源碼中學(xué)習(xí)」面試官都不知道的Vue題目答案
「從源碼中學(xué)習(xí)」Vue源碼中的JS騷操作
「從源碼中學(xué)習(xí)」徹底理解Vue選項(xiàng)Props
「Vue實(shí)踐」項(xiàng)目升級(jí)vue-cli3的正確姿勢(shì)
為何你始終理解不了JavaScript作用域鏈?
公眾號(hào)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/7237.html
摘要:只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙只有動(dòng)手,你才能真正掌握一門技術(shù)持續(xù)更新中項(xiàng)目地址求求求源碼系列跟一起學(xué)如何寫函數(shù)庫(kù)中高級(jí)前端面試手寫代碼無敵秘籍如何用不到行代碼寫一款屬于自己的類庫(kù)原理講解實(shí)現(xiàn)一個(gè)對(duì)象遵循規(guī)范實(shí)戰(zhàn)手摸手,帶你用擼 Do it yourself!!! 只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙 只有動(dòng)手,你才能真正掌握一門技術(shù) 持續(xù)更新中…… 項(xiàng)目地址 https...
摘要:記錄下我遇到的面試題,都有大佬分享過,附上各個(gè)大佬的文章,總結(jié)出其中的主要思想即可。推薦黑金團(tuán)隊(duì)的文章前端緩存最佳實(shí)踐推薦名揚(yáng)的文章淺解強(qiáng)緩存和協(xié)商緩存狀態(tài)碼重點(diǎn)是等,要給面試官介紹清楚。前言 在這互聯(lián)網(wǎng)的寒冬臘月時(shí)期,雖說過了金三銀四,但依舊在招人不斷。更偏向于招聘高級(jí)開發(fā)工程師。本人在這期間求職,去了幾家創(chuàng)業(yè),小廠,大廠廝殺了一番,也得到了自己滿意的offer。 整理一下自己還記得的面試...
摘要:雖然構(gòu)造函數(shù)或者對(duì)象字面量的方法都可以用來創(chuàng)建對(duì)象,但是這些方法使用同一個(gè)接口創(chuàng)建很多對(duì)象,會(huì)產(chǎn)生大量的重復(fù)代碼。參考資料冴羽的專題系列中高級(jí)前端面試手寫代碼無敵秘籍前端筆試之手寫代碼一本系列會(huì)從面試的角度出發(fā)圍繞JavaScript,Node.js(npm包)以及框架三個(gè)方面來對(duì)常見的模擬實(shí)現(xiàn)進(jìn)行總結(jié),具體源代碼放在github項(xiàng)目上,長(zhǎng)期更新和維護(hù) showImg(https://use...
摘要:獲取的對(duì)象范圍方法獲取的是最終應(yīng)用在元素上的所有屬性對(duì)象即使沒有代碼,也會(huì)把默認(rèn)的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對(duì)于一個(gè)光禿禿的元素,方法返回對(duì)象中屬性值如果有就是據(jù)我測(cè)試不同環(huán)境結(jié)果可能有差異而就是。 花了很長(zhǎng)時(shí)間整理的前端面試資源,喜歡請(qǐng)大家不要吝嗇star~ 別只收藏,點(diǎn)個(gè)贊,點(diǎn)個(gè)star再走哈~ 持續(xù)更新中……,可以關(guān)注下github 項(xiàng)目地址 https:...
摘要:能在面試時(shí)有限的時(shí)間里,能夠快速抓住重點(diǎn)與面試官交流。這些知識(shí)點(diǎn)屬于加分項(xiàng),如果能在面試時(shí)從容侃侃而談,想必面試官會(huì)記憶深刻,為你折服的引言 本篇文章會(huì)繼續(xù)沿著前面兩篇的腳步,繼續(xù)梳理前端領(lǐng)域一些比較主流的進(jìn)階知識(shí)點(diǎn),力求能讓大家在橫向?qū)用嬗袀€(gè)全面的概念。能在面試時(shí)有限的時(shí)間里,能夠快速抓住重點(diǎn)與面試官交流。這些知識(shí)點(diǎn)屬于加分項(xiàng),如果能在面試時(shí)從容侃侃而談,想必面試官會(huì)記憶深刻,為你折服的~...
閱讀 3051·2021-11-16 11:45
閱讀 5413·2021-09-22 10:57
閱讀 1824·2021-09-08 09:36
閱讀 1697·2021-09-02 15:40
閱讀 2563·2021-07-26 23:38
閱讀 1302·2019-08-30 15:55
閱讀 990·2019-08-30 15:54
閱讀 1274·2019-08-29 14:06