call/apply/bind
call是接收一个数组 apply是接受一串参数 bind返回一个函数,绑定到对象上,接受一串参数
核心
方法绑定到
Function.prototype
上三者都是截取对象的方法作为参数绑定到对象上,所以在Function的prototype上所有对象都能访问。this是要截取绑定的对象,(函数/方法也是一种对象)这里三个例子是Array的splice方法
- 不能直接用this(…args)方式调用需要赋值给调用对象的属性,因为要绑定到对象上
- 用完之后要删除fn,否则会在对象上新增一个fn属性
实现
- 绑定到Function.prototype原型对象上要实现的方法
- 要绑定的对象中加入截取的方法(实现绑定)
- 执行完成后删除刚刚绑定的属性(截取的方法)
实现call,myCall
```javascript
/**
- 函数原型上加上、
- this —- 原生call截取的函数 这里是调用myCall的那个对象(函数也是一种对象)(函数,Array.prototype.splice.myCall)
- @param {*} context 作用于的对象,不传递则作用在window上
- @param {…any} args 其他参数 */ Function.prototype.myCall = function (context = window, …args) { context.fn = this; const result = context.fn(…args); // delete context.fn; return result; }
// 测试
const arr = [1, 2, 3, 4, 5, 6] const res = Array.prototype.slice.myCall(arr, 2) console.log(res) console.log(arr) // 如果不delete context.fn,则数组中将带一个fn函数

<a name="X2azD"></a>
### 实现apply myApply
```javascript
/**
* apply截取对象的方法,第二个为一堆参数
*
* 函数原型上加上
*
* this --- 原生call截取的函数 这里是调用myApply 的那个对象(函数也是一种对象)(函数,Array.prototype.splice.myApply )
* @param {*} context 作用于的对象,不传递则作用在window上
* @param {...any} args 其他参数
*/
Function.prototype.myApply = function (context = window, ...args) {
context.fn = this;
let result;
if (args.length === 0) {
result = context.fn();
} else {
result = context.fn(...args);
}
delete context.fn;
return result;
}
// 测试
const arr = [1, 2, 3, 4, 5, 6]
// 从0的位置删除1个添加7、8、9三个元素
const res = Array.prototype.splice.myApply(arr)
console.log(res, arr)
// console.log(arr) // 如果不delete context.fn,则数组中将带一个fn函数
实现bind myBind
/**
* bind截取对象的方法,第二个为一堆参数
*
* 函数原型上加上
*
*/
Function.prototype.myBind = function () {
if (typeof this !== 'function') throw new TypeError('not a function')
// 将参数拆解为数组(arguments伪数组)
let args = Array.prototype.slice.call(arguments);
// 获取方法要要绑定到的对象(数组第一项)
let _this = args.shift();
// 获取原要绑定到对象上的函数
let self = this;
// 返回一个函数
return function () {
return self.apply(_this, args);
}
}
// 测试
const arr = [1, 2, 3, 4, 5, 6]
// 从1的位置删除1个添加222一个元素
const res = Array.prototype.splice.myBind(arr, 1, 1, 222)()
console.log(res, arr)
// console.log(arr) // 如果不delete context.fn,则数组中将带一个fn函数
instanceof
instanceof的用法
判断一个对象是否是一个类(构造函数)的实例
核心
- 一个对象构造函数的prototype和这个对象的proto是一个对象
- prototype是函数上才有的属性
- proto是对象上的属性
实现
- 拿到构造函数的prototyoe,循环向上找要查询对象的proto,如果对象是构造函数的一个实例则一定会找到相同的原型对象
循环
```javascript /**- @param {*} L instanceof 左边的参数
- @param {} R instanceof 右边的参数
/
function myInstanceOf(L, R) {
// 拿到目标显式(非隐式)原型
let O = R.prototype;
L = L.proto;
while (true) {
if (L === null || L === undefined) {
} if (O === L) {return false;
} // 找L对象的原型 L = L.proto; } }return true;
const a = [1, 2, 3, 4, 5, 6, 7] console.log(a instanceof Array) console.log(myInstanceOf(a, Array))
<a name="9mSfN"></a>
### 递归
```javascript
/**
*
* @param {*} L instanceof 左边的参数
* @param {*} R instanceof 右边的参数
*/
function myInstanceOfWithRecu(L, R) {
// 拿到目标显式(非隐式)原型
let O = R.prototype;
L = L.__proto__;
if (L === null || L === undefined) {
return false;
}
if (O === L) {
return true;
}
// 递归找L对象的原型
return myInstanceOf(L.__proto__, R)
}
const a = [1, 2, 3, 4, 5, 6, 7]
console.log(a instanceof Array)
console.log(myInstanceOf(a, Array))
Object.create
Object.create()
方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。
实现
- 创建一个函数
- 函数prototype指向要继承的对象
- 用这个函数创建一个实例
```javascript
/**
- @param {} proto 要继承的原型 / function myCreate(proto) { function F() { }; F.prototype = proto; return new F(); }
const person = {
isHuman: false,
printIntroduction: function () {
console.log(My name is ${this.name}. Am I human? ${this.isHuman}
);
}
};
const me = myCreate(person);
me.name = ‘Matthew’; // “name” is a property set on “me”, but not on “person” me.isHuman = true; // inherited properties can be overwritten me.printIntroduction(); // expected output: “My name is Matthew. Am I human? true” console.log(person, me)
<br />MDN<br />[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
<a name="JBTgd"></a>
## map/filter/reduce
> 三个有代表性的迭代函数
> map react中遍历元素常用的
> filter 过滤后的值
> reduce 累加
<a name="Nv0o4"></a>
### map
**参数**<br />`[].map((item, index, arr)=>{})`<br />map是有返回值的,把数组迭代,每一个元素都应用传递进入的方法,生成一个新的数组<br />**核心**
- this是调用myMap的对象(数组也是一种对象)
- 新开辟一个数组res用于存放结果,遍历要处理的数组,把每一个元素应用传递进来的方法,把值push到这个开辟的res中,返回这个res
```javascript
/**
*
* this --- 调用myMap方法的对象
* @param {*} cb map方法接收的一个参数
*/
Array.prototype.myMap = function (cb) {
if (typeof cb !== 'function') {
return [];
}
const res = [];
const arr = this
for (let i = 0; i < arr.length; i++) {
res.push(cb(arr[i], i, arr));
}
return res;
}
// const a = [1, 2, 3, 4, 5, 6, 7]
// const res = a.map(x => x * 2)
// console.log(a, res)
const a = [1, 2, 3, 4, 5, 6, 7]
const res = a.myMap(x => x * 2)
console.log(a, res)
filter
[].filter((item, index, arr)=>{})
返回一个满足条件的新数组
核心
开辟一个数组res,遍历要处理的数组,把每一个元素应用传递进来的方法,把符合条件的元素push到这个开辟的res中,返回这个res ```javascript /**
- this —- 调用myFilter方法的对象
@param {} cb filter方法接收的一个参数 / Array.prototype.myFilter = function (cb) { if (typeof cb !== ‘function’) {
return [];
} const res = []; const arr = [] for (let i = 0; i < this.length; i++) {
// 满足条件的push到数组中 if (cb(arr[i], i, arr)) { res.push(arr[i]); }
}
return res; }
// const a = [1, 2, 3, 4, 5, 6, 7] // const res = a.filter(x => x > 2) // console.log(a, res)
const a = [1, 2, 3, 4, 5, 6, 7] const res = a.myFilter(x => x > 2) console.log(a, res)
<a name="PKOC0"></a>
### reduce
`arr.reduce((acc, cur, index, arr) => {}, initValue)`
- acc 累加值
- cur 当前值
- index 当前索引
- arr 原数组
返回值:累加值 acc
```javascript
/**
*
* this --- 调用myMap方法的对象
* @param {*} cb reduce方法接收的第一个参数
* @param {*} initValue reduce方法接收的第二个参数初始值
*/
Array.prototype.myReduce = function (cb, initValue) {
// 如果调用的是null或undefined
if (this === null) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
// 如果回调函数不是函数
if (typeof cb !== 'function') {
throw new TypeError(cb + ' is not a function');
}
// 如果调用的不是数组
if (!Array.isArray(this)) {
throw new TypeError("not a array");
}
// 数组为空,并且没有初始值
if (this.length === 0 && arguments.length < 2) {
throw new TypeError('Reduce of empty array with no initial value');
}
const arr = this;
let res = null; // 要累加的值
// 判断有没有初始值
if (arguments.length > 1) {
res = initValue;
} else {
res = arr.splice(0, 1)[0]; //没有就取第一个值
}
arr.forEach((item, index) => {
res = cb(res, item, index, arr); // cb 每次执行完都会返回一个新的 res值,覆盖之前的 res
})
return res;
}
// const a = [1, 2, 3, 4, 5, 6, 7]
// const res = a.reduce((acc, cur) => acc + cur, 10000)
// console.log(a, res)
const a = [1, 2, 3, 4, 5, 6, 7]
const res = a.myReduce((acc, cur) => acc + cur, 10000)
console.log(a, res)