面試 JavaScript 框架八股文十問十答第七期
作者:程序員小白條,個(gè)人博客
相信看了本文后,對你的面試是有一定幫助的!關(guān)注專欄后就能收到持續(xù)更新!
?點(diǎn)贊?收藏?不迷路!?文章來源地址http://www.zghlxwxcb.cn/news/detail-830397.html
1)原型修改、重寫
在 JavaScript 中,可以通過修改或重寫對象的原型來改變對象的行為。原型修改指的是直接修改對象的原型,而原型重寫指的是創(chuàng)建一個(gè)新的對象,并將其作為原型賦值給目標(biāo)對象。這兩種操作都會影響到所有基于該原型創(chuàng)建的實(shí)例。
示例:
function Person(name) {
this.name = name;
}
// 修改原型
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.name);
};
const john = new Person("John");
john.sayHello(); // 輸出: Hello, I'm John
// 重寫原型
Person.prototype = {
sayGoodbye: function() {
console.log("Goodbye!");
}
};
const alice = new Person("Alice");
// john.sayHello(); // 報(bào)錯(cuò):john.sayHello is not a function
alice.sayGoodbye(); // 輸出: Goodbye!
在上面的示例中,首先修改了 Person
的原型,添加了 sayHello
方法,然后重寫了 Person
的原型,賦值一個(gè)新對象。因此,對于之前創(chuàng)建的 john
對象,仍然可以調(diào)用 sayHello
方法,但對于之后創(chuàng)建的 alice
對象,則無法調(diào)用 sayHello
方法。
2)原型鏈指向
在 JavaScript 中,每個(gè)對象都有一個(gè)原型(prototype)屬性,它指向另一個(gè)對象,這個(gè)對象就是當(dāng)前對象的原型。通過原型鏈,對象可以訪問其他對象的屬性和方法。
當(dāng)試圖訪問一個(gè)對象的屬性或方法時(shí),如果該對象本身沒有定義該屬性或方法,JavaScript 引擎會沿著原型鏈向上查找,直到找到該屬性或方法或者到達(dá)原型鏈的終點(diǎn)為止。
3)原型鏈的終點(diǎn)是什么?
在 JavaScript 中,原型鏈的終點(diǎn)是 null
。當(dāng)試圖訪問一個(gè)對象的屬性或方法時(shí),如果在對象本身及其原型鏈上都找不到該屬性或方法,則返回 undefined
。原型鏈的終點(diǎn)是 null
是因?yàn)?null
是 JavaScript 中的原始值之一,不是對象,因此沒有原型。
const obj = {};
console.log(obj.toString()); // 輸出: [object Object]
在上面的示例中,obj
對象本身沒有定義 toString
方法,但由于 obj
的原型鏈上存在 Object.prototype.toString
方法,因此可以調(diào)用成功。如果在整個(gè)原型鏈上都找不到 toString
方法,則會返回 undefined
。
4)如何打印出原型鏈的終點(diǎn)?
要打印出原型鏈的終點(diǎn),可以通過循環(huán)訪問對象及其原型鏈,并判斷原型是否為 null
。以下是一個(gè)簡單的方法:
function printPrototypeChain(obj) {
let currentObj = obj;
while (currentObj !== null) {
console.log(currentObj);
currentObj = Object.getPrototypeOf(currentObj);
}
}
const exampleObj = {}; // 你可以替換為具體的對象
printPrototypeChain(exampleObj);
這個(gè)函數(shù)會依次打印出對象及其原型鏈上的所有對象,直到原型為 null
。
5)如何獲得對象非原型鏈上的屬性?
要獲得對象自身的屬性(即非原型鏈上的屬性),可以使用 Object.keys()
、Object.values()
或 Object.entries()
方法。這些方法會返回對象自身可枚舉屬性的鍵、值或鍵值對。
示例:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.name);
};
const john = new Person("John", 30);
// 獲取對象自身的屬性
const ownProperties = Object.keys(john);
console.log(ownProperties); // 輸出: ["name", "age"]
// 或者使用 for...in 循環(huán)
for (const prop in john) {
if (john.hasOwnProperty(prop)) {
console.log(prop); // 輸出: "name", "age"
}
}
在上述示例中,Object.keys(john)
返回 john
對象自身的屬性數(shù)組,即 ["name", "age"]
。
6)對閉包的理解
閉包是指在函數(shù)內(nèi)部創(chuàng)建的函數(shù),它可以訪問包含它的外部函數(shù)的變量,即使外部函數(shù)已經(jīng)執(zhí)行完畢。閉包是 JavaScript 中強(qiáng)大且常見的特性,可以用于創(chuàng)建私有變量、實(shí)現(xiàn)模塊化等。
簡單說,閉包就是一個(gè)函數(shù)和其相關(guān)的引用環(huán)境的組合。當(dāng)函數(shù)被定義時(shí),它就記住了自己被創(chuàng)建時(shí)的作用域,即使在其定義的地方之外調(diào)用它,它依然可以訪問這個(gè)作用域內(nèi)的變量。
function outerFunction() {
let outerVar = "I am from outer function";
function innerFunction() {
console.log(outerVar);
}
return innerFunction;
}
const closureExample = outerFunction();
closureExample(); // 輸出: I am from outer function
在這個(gè)例子中,innerFunction
是一個(gè)閉包,它可以訪問 outerFunction
中聲明的 outerVar
變量,即使 outerFunction
已經(jīng)執(zhí)行完畢。通過將 innerFunction
賦值給 closureExample
,我們創(chuàng)建了一個(gè)閉包,可以在之后的任何時(shí)候調(diào)用它,而它仍然能夠訪問到 outerVar
。
7)對作用域、作用域鏈的理解
作用域(Scope): 作用域是指在程序中定義變量的區(qū)域,它規(guī)定了變量的可訪問性和生命周期。在 JavaScript 中,有全局作用域和局部作用域。全局作用域指的是在整個(gè)程序中都可訪問的范圍,而局部作用域則是在函數(shù)內(nèi)部或塊級作用域中定義的變量范圍。
作用域鏈(Scope Chain): 作用域鏈?zhǔn)侵冈?JavaScript 中,每個(gè)函數(shù)都有一個(gè)作用域鏈,用于查找變量。當(dāng)在一個(gè)函數(shù)內(nèi)訪問一個(gè)變量時(shí),JavaScript 引擎會首先查找當(dāng)前函數(shù)的作用域,如果找不到就會順著作用域鏈向上查找,直到找到該變量或到達(dá)全局作用域。
8)對執(zhí)行上下文的理解
執(zhí)行上下文(Execution Context): 執(zhí)行上下文是 JavaScript 中代碼執(zhí)行的環(huán)境,包含了變量對象、作用域鏈、this 指向等信息。每次調(diào)用函數(shù)時(shí),都會創(chuàng)建一個(gè)新的執(zhí)行上下文。全局上下文是在程序開始執(zhí)行時(shí)創(chuàng)建的,每個(gè)函數(shù)調(diào)用都會創(chuàng)建一個(gè)新的函數(shù)執(zhí)行上下文。
執(zhí)行上下文分為三種類型:
- 全局執(zhí)行上下文: 在程序執(zhí)行之初創(chuàng)建,全局上下文是唯一的,負(fù)責(zé)整個(gè)程序的執(zhí)行。
- 函數(shù)執(zhí)行上下文: 每次調(diào)用函數(shù)時(shí)創(chuàng)建,包含了函數(shù)的局部變量和參數(shù)。
-
eval 函數(shù)執(zhí)行上下文: 在使用
eval
函數(shù)時(shí)創(chuàng)建,eval 函數(shù)可以動(dòng)態(tài)地執(zhí)行一段 JavaScript 代碼。
9)對this對象的理解
this 對象: 在 JavaScript 中,this
是一個(gè)關(guān)鍵字,代表當(dāng)前執(zhí)行代碼的對象。具體指向的對象取決于函數(shù)的調(diào)用方式。在全局上下文中,this
指向全局對象(在瀏覽器環(huán)境中通常是 window
),而在函數(shù)內(nèi)部,this
的值取決于函數(shù)的調(diào)用方式。
示例:
function exampleFunction() {
console.log(this);
}
exampleFunction(); // 在瀏覽器中,輸出: window
const obj = {
method: function() {
console.log(this);
}
};
obj.method(); // 輸出: obj 對象
10)call() 和 apply() 的區(qū)別?
call()
和 apply()
都是 JavaScript 中用于調(diào)用函數(shù)的方法,它們的作用是改變函數(shù)執(zhí)行時(shí)的上下文(即 this
的值)。它們的區(qū)別在于傳遞參數(shù)的方式。
-
call() 方法:
call()
方法接收一個(gè)參數(shù)列表,參數(shù)之間用逗號分隔。function greet(name) { console.log(`Hello, ${name}! I am ${this.title}.`); } const person = { title: 'Mr.' }; greet.call(person, 'John');
-
apply() 方法:
apply()
方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)是函數(shù)執(zhí)行時(shí)的上下文,第二個(gè)參數(shù)是一個(gè)數(shù)組或類數(shù)組對象,包含了傳遞給函數(shù)的參數(shù)。function greet(name) { console.log(`Hello, ${name}! I am ${this.title}.`); } const person = { title: 'Mr.' }; greet.apply(person, ['John']);
總的來說,call()
和 apply()
的目的都是在特定的上下文中調(diào)用函數(shù),只是傳遞參數(shù)的方式不同。在現(xiàn)代 JavaScript 中,通常使用擴(kuò)展運(yùn)算符 ...
來代替 apply()
,因?yàn)樗`活,同時(shí)不需要明確指定上下文。
開源項(xiàng)目地址:https://gitee.com/falle22222n-leaves/vue_-book-manage-system
已 300 + Star!文章來源:http://www.zghlxwxcb.cn/news/detail-830397.html
?點(diǎn)贊?收藏?不迷路!?
到了這里,關(guān)于面試 JavaScript 框架八股文十問十答第七期的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!