js常考的面试题重新整理
// call
Function.prototype.mycall = function(context) {
// 1. 将传递给mycall的第一个参数作为函数内部的上下文,如果没有传递参数,则默认为全局对象window。
context = context || window;
// 2. 在传递的上下文对象中创建一个临时属性fn,并将当前函数(即调用mycall的函数)赋值给这个属性。
content.fn = this;
// 3. 通过将剩余的参数(除了第一个参数context之外)转换为数组,然后使用展开运算符(...)调用函数。
let arg = [...arguments].slice(1);
let result = content.fn(...arg);
// 4. 删除临时属性fn,以避免污染传递的上下文对象。
delete content.fn;
// 5. 返回函数执行的结果。
return result;
}
这段代码的主要作用是将一个函数作为方法调用,同时自定义了函数内部的this上下文。具体步骤如下:
-
首先,通过
context参数来指定要设置为函数内部this的上下文。如果没有传递context参数,它将默认为全局对象window。 -
在传递的上下文对象(
context)中创建了一个临时属性fn,并将当前调用mycall方法的函数(即调用mycall的函数)赋值给这个属性。这样可以在上下文中调用函数,而且函数内部的this将会指向上下文对象。 -
通过将剩余的参数(除了第一个参数
context之外)转换为数组,然后使用展开运算符...调用函数。这些参数将作为函数的参数传递给函数。 -
执行函数后,删除临时属性
fn,以避免污染传递的上下文对象。 -
最后,返回函数执行的结果。
这样,使用mycall方法可以实现自定义的call功能,允许您调用函数并指定函数内部的this上下文,同时传递参数。例如:
function greet(message) {
console.log(message + ", " + this.name);
}
const person = { name: "Alice" };
greet.mycall(person, "Hello"); // 输出 "Hello, Alice"
实现apply
Function.prototype.myapply = function(content) {
// 1. 将传递给myapply的第一个参数作为函数内部的上下文,如果没有传递参数,则默认为全局对象window。
content = content || window;
// 2. 在传递的上下文对象中创建一个临时属性fn,并将当前函数(即调用myapply的函数)赋值给这个属性。
content.fn = this;
// 3. 使用arguments[1]来获取传递给myapply的第二个参数,它应该是一个数组或类似数组的对象,其中包含要传递给函数的参数。
let result;
if (arguments[1]) {
result = content.fn(...arguments[1]);
} else {
result = content.fn();
}
// 4. 删除临时属性fn,以避免污染传递的上下文对象。
delete content.fn;
// 5. 返回函数执行的结果。
return result;
}
这段代码的主要作用是允许您调用函数,并指定函数内部的this上下文,同时传递一个参数数组。
具体步骤如下:
-
首先,将传递给
myapply的第一个参数作为函数内部的上下文。如果没有传递参数,将默认使用全局对象window作为上下文。 -
在传递的上下文对象(
content)中创建了一个临时属性fn,并将当前调用myapply方法的函数(即调用myapply的函数)赋值给这个属性。这样可以在上下文中调用函数,而且函数内部的this将会指向上下文对象。 -
使用
arguments[1]来获取传递给myapply的第二个参数,它应该是一个数组或类似数组的对象,其中包含要传递给函数的参数。如果存在第二个参数,就使用展开运算符(...)来将参数数组传递给函数;否则,直接调用函数。 -
执行函数后,删除临时属性
fn,以避免污染传递的上下文对象。 -
最后,返回函数执行的结果。
这样,使用myapply方法可以模拟apply方法的行为,允许您在调用函数时指定上下文并传递参数数组。例如:
function greet(message) {
console.log(message + ", " + this.name);
}
const person = { name: "Alice" };
greet.myapply(person, ["Hello"]); // 输出 "Hello, Alice"
//bind
Function.prototype.mybind = function(content) { // 1. 首先,检查当前函数是否为一个函数。 if (typeof this !== 'function') { throw new Error('not a function'); } // 2. 保存当前函数的引用,以备后续使用。 let _this = this; // 3. 提取除了第一个参数(content)之外的其他参数,这些参数将会在新函数被调用时传递给原函数。 let arg = [...arguments].slice(1); // 4. 返回一个新函数F,它可以根据如下规则调用原函数: return function F() { // 5. 如果新函数F通过构造函数方式调用(即使用new关键字),则会将原函数当作构造函数来调用,创建一个新对象并返回。 if (this instanceof F) { return new _this(...arg, ...arguments); } // 6. 如果新函数F通过普通函数调用(即不使用new关键字),则将原函数作为方法调用,并传递上下文和参数。 return _this.apply(content, arg.concat(...arguments)); } }
这段代码的主要作用是创建一个新函数,该新函数在调用时会根据上下文对象(content)来调用原函数(this)。具体步骤如下:
-
首先,检查当前函数是否为一个函数。如果不是函数,则抛出一个错误。
-
保存当前函数的引用,以备后续使用,因为在返回的新函数中需要使用原函数。
-
提取除了第一个参数(
content)之外的其他参数,这些参数将会在新函数被调用时传递给原函数。 -
返回一个新的函数
F,它可以根据如下规则调用原函数:-
如果新函数
F通过构造函数方式调用(即使用new关键字),则会将原函数当作构造函数来调用,创建一个新对象并返回。这样可以确保this关键字在原函数内部指向新对象。 -
如果新函数
F通过普通函数调用(即不使用new关键字),则将原函数作为方法调用,并传递上下文对象(content)和参数。这里使用apply方法来调用原函数。
-
通过这种方式,mybind方法创建了一个新函数,该新函数具有永久性的上下文绑定,并且可以在需要时传递参数。例如:
function greet(message) { console.log(message + ", " + this.name); } const person = { name: "Alice" }; const boundGreet = greet.mybind(person, "Hello"); boundGreet(); // 输出 "Hello, Alice"
// new
function myNew() { // 1. 创建一个空对象obj。 let obj = {}; // 2. 从参数中取出第一个参数(通常是构造函数),并将其赋值给Constructor变量。 let Constructor = [].shift.call(arguments); // 3. 将obj的原型对象(__proto__属性)设置为构造函数的prototype属性,以建立原型链。 obj.__proto__ = Constructor.prototype; // 4. 使用apply方法调用构造函数,并将obj作为this关键字绑定到构造函数内部。 let result = Constructor.apply(obj, arguments); // 5. 返回根据构造函数执行的结果决定的对象。如果构造函数显式返回一个对象,则返回该对象,否则返回创建的obj对象。 return typeof result === 'object' ? result : obj; }
这段代码的主要作用是模拟new操作符的行为,它接受任意数量的参数,并执行以下步骤:
-
创建一个空对象
obj,它将成为构造函数的实例。 -
使用
[].shift.call(arguments)从传递给myNew的参数中获取第一个参数,这通常应该是一个构造函数。这将在后续步骤中用于创建对象实例。 -
将
obj的原型对象 (__proto__属性) 设置为构造函数的prototype属性,以建立原型链。这是为了确保新创建的对象可以继承构造函数原型上的属性和方法。 -
使用
Constructor.apply(obj, arguments)调用构造函数,将obj作为this关键字绑定到构造函数内部,同时传递剩余的参数给构造函数。这样构造函数内部的代码可以对obj进行初始化操作。 -
最后,根据构造函数的执行结果,决定返回的对象。如果构造函数显式返回一个对象,那么就返回该对象;否则,返回创建的
obj对象。
这样,myNew 函数模拟了 new 操作符的行为,可以用来创建对象实例,就像使用 new 一样。例如:
function Person(name, age) { this.name = name; this.age = age; } const person = myNew(Person, "Alice", 30); console.log(person.name); // 输出 "Alice" console.log(person.age); // 输出 30

浙公网安备 33010602011771号