II OOP / protoType
OOP / ProtoType

JavaScript 数据类型
基本类型:存储在栈,传递的是当前的值,修改不会影响原先的值;
引用类型:索引的引用地址,存储在栈,其值存储在堆中。
手写 call
/ apply
/ bind
call
/ apply
/ bind
// Function.prototype._apply = function () {
Function.prototype.__call = function () {
// const [caller, args] = arguments;
const [caller, ...args] = arguments;
caller._callFn = this;
const res = caller._callFn(...args);
delete caller._callFn;
return res;
}
bind - 1
参数略有区别,会合并参数
bind - 1
参数略有区别,会合并参数// 先实现普通版 bind
Function.prototype.__bind = function () {
const calledFn = this;
const [binder, ...args] = arguments;
const bindFn = function () {
return calledFn.call(
// 判断是否 被当作了构造函数
binder,
...args,
...arguments,
)
}
return bindFn;
}
bind - 2
bind
后的函数还可以作为构造器
使用 这该如何实现?
bind - 2
bind
后的函数还可以作为构造器
使用 这该如何实现?bind - 2
实现前要先看下new
是如何实现的或者其内部的机制如何
// 构造函数 Foo() { ... }
当代码
new Foo(...)
执行时,会发生以下事情:
一个继承自
Foo.prototype
的新对象被创建。使用指定的参数调用构造函数
Foo
,并将this
绑定到新创建的对象。
new Foo
等同于new Foo
()
,也就是没有指定参数列表,Foo
不带任何参数调用的情况。由构造函数返回的对象就是
new
表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤 1 创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)【参考链接】: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new
/**
* 因为 new 为特殊操作符,所以用 function 来代替实现
*/
function operatorNew(_Constructor, ...args) {
// 以 _Constructor.prototype 为原型创建空对象。
const tempObj = Object.create(_Constructor.prototype);
// 以新创建的空对象作为 this 调用构造函数 _Constructor
const constructRes = _Constructor.apply(tempObj, args);
// 判断构造函数返回结果是否为对象。
const resObj = typeof constructRes === 'object'
? constructRes
: tempObj;
return resObj;
}
从上面代码的7-9
行可以看出如下两个细节
构造函数被调用时,需要接收新的
this
新的
this
是以构造函数原型为原型创建的
// 改造如下⬇️
/**
* ......
* line 2 ~ line 5
*/
const bindFn = function () {
return calledFn.call(
// 判断是否 被当作了构造函数
// 当作为构造函数执行时,this指向以构造函数为原型创建的对象,所以有如下逻辑⬇️
// 1. [this]为[bind]生成函数的实例时,即代表其是通过[new]操作符生成的实例函数,所以[bind]生成的函数需要绑定 [this]作为新的上下文。 对应上方[new]实现第[9]行代码
this instanceof bindFn ? this : binder,
...args,
...arguments,
)
}
// 这一步是为了能够在 new 操作的第一步创建空对象时获取到正确的(构造函数的) prototype
bindFn.prototype = this.prototype
return bindFn;
类数组
只有基本元素及length
属性
小记
slice
splice
区别⬇️
slice
不改变原数组,slice
仅读取
splice
改变原数组,splice
支持替换
arguments.callee
一个已经弃用的属性
通过该方法可以在函数内部获取函数自身
主要用于解决在匿名函数内部获取函数自身
继承实现的方式方法
以上描述及解决方案均属个人观点,若您存在任何疑问及意见,还请联系本人 ✉️ 邮箱。
最后更新于
这有帮助吗?