apply&call
Function.prototype.myApply = function (context, args) {
// 不同点一:call函数需要把参数写成rest参数(...args)
//Function.prototype.myCall = function (context, ...args) {
// 如果 context 为 null 或 undefined,则设置为 globalThis
context = context || globalThis;
// 创建一个唯一的属性名,防止覆盖原有属性
const fnSymbol = Symbol();
// 将当前函数(this)赋值给 context 对象的临时属性
context[fnSymbol] = this;
// 调用该函数并保存结果
const result = context[fnSymbol](...(args || []));
// 删除 context 中的临时属性
delete context[fnSymbol];
// 返回结果
return result;
};
// 测试代码
function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
const person = {
name: 'Alice'
};
// 使用 myApply
const result = greet.myApply(person, ['Hello', '!']);
// 不同点二:call函数需要把参数写成以,分割的形式而不是数组
//const result = greet.myCall(person, 'Hello', '!');
console.log(result); // 输出: "Hello, Alice!"
解释
-
设置上下文:
context = context || globalThis;:确保如果传入的context为null或undefined,则将其设置为全局对象globalThis。
-
创建唯一属性名:
const fnSymbol = Symbol();:使用Symbol创建一个唯一的属性名,以防止覆盖context对象上的任何现有属性。
-
将函数绑定到上下文:
context[fnSymbol] = this;:将当前函数(this)赋值给context对象的临时属性,使用唯一的符号属性名fnSymbol。
-
调用函数并传递参数:
const result = context[fnSymbol](...(args || []));:使用展开运算符(...)来传递参数数组args。如果args为null或undefined,则使用空数组。
-
清理:
delete context[fnSymbol];:删除添加到context对象的临时属性,避免对原始对象的污染。
-
返回结果:
return result:返回调用函数的结果。
使用示例
以下是另一个使用 myApply 的示例:
function add(a, b) {
return a + b;
}
const result = add.myApply(null, [5, 10]);
console.log(result); // 输出: 15
bind
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>手写 bind 函数示例</title>
<style>
#content {
height: 2000px;
background: linear-gradient(to bottom, #ffefba, #ffffff);
}
</style>
</head>
<body>
<div id="content">
<h1>查看控制台以了解手写 bind 函数的输出</h1>
</div>
<script>
Function.prototype.myBind = function (context, ...args) {
// 保存 this,即调用 myBind 的函数
const fn = this;
// 返回一个新的函数
const boundFunction = function (...newArgs) {
// 检查新函数是否作为构造函数使用
if (this instanceof boundFunction) {
// 如果是构造函数,则使用 this 作为上下文,并忽略传入的 context
return new fn(...args, ...newArgs);
} else {
// 如果不是构造函数,则使用指定的 context
return fn.apply(context, [...args, ...newArgs]);
}
};
// 将原型链连接到绑定的函数
boundFunction.prototype = Object.create(fn.prototype);
return boundFunction;
};
// 测试代码
function Greet(greeting, punctuation) {
this.name = 'Alice';
this.message = `${greeting}, ${this.name}${punctuation}`;
}
const person = {
name: 'Bob'
};
// 使用 myBind
const BoundGreet = Greet.myBind(person, 'Hello');
// 使用 new 操作符创建一个新的实例
const instance = new BoundGreet('!');
console.log(instance.message); // 输出: "Hello, Alice!"
// 检查是否为实例
console.log(instance instanceof Greet); // 输出: true
console.log(person,'person') // 'jsCode.html:61 {name: 'Bob'} 'person''
</script>
</body>
</html>
原型和原型链的理解
// 定义一个构造函数
function Animal(name) {
this.name = name;
}
// 在原型上添加方法
Animal.prototype.speak = function() {
console.log(`${this.name} makes a noise.`);
};
// 创建一个实例
const dog = new Animal('Dog');
dog.speak(); // 输出:Dog makes a noise.
console.log(dog.__proto__ === Animal.prototype); // true
console.log(Animal.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
dog是Animal的一个实例。dog.__proto__指向Animal.prototype。Animal.prototype.__proto__指向Object.prototype。Object.prototype.__proto__指向null,即原型链的终点。
通过这些关系,我们可以看到 dog 可以访问 Animal.prototype 上的 speak 方法,而如果 Animal.prototype 没有这个方法,它会继续查找 Object.prototype。
总结
- 原型(Prototype) 是一个对象,它被其他对象用来继承属性和方法。
- 原型链(Prototype Chain) 是由对象及其原型组成的链,通过它可以实现属性和方法的继承。
- 每个对象都有一个
__proto__属性,指向其构造函数的prototype对象。 - 原型链的终点是
Object.prototype,它的__proto__是null。
233

被折叠的 条评论
为什么被折叠?



