js實現call
// example
let obj = {
a: 124,
b: 'ccc'
};
function fn(c) {
return this.a + this.b + this.c;
}
// 使用call是這樣轉換的
// step 1: 生成新的函數,新的執行上下文(通過在傳入對象中增加調用方法)
const obj = {
a: 124,
b: 'ccc',
fn: function(c) {
return this.a + this.b + this.c;
}
}
// step2: 執行 obj.fn(333);
let res = obj.fn(333);
// step3: obj被改變,得恢復原來的值
delete obj.fn;
Function.prototype.myCall = function(context) {
const newContext = context || window;
newContext.fn = this;
const args = [];
for(let i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
const res = newContext.fn(...args);
delete newContext.fn;
return res;
}
console.log(fn.myCall(obj, 'cccc'));
js實現apply
Function.prototype.myApply = function(context, arr) {
const newContext = context || window;
newContext.fn = this;
const args = [];
let res;
if (!arr) {
res = newContext.fn(...args);
}
else {
if (!(arr instanceof Array)) {
throw new Error('params must be array');
}
result = context.fn(...arr);
}
delete newContext.fn;
return res;
}
console.log(fn.myApply(obj, ['cccc']));
call & apply
Math.max.apply(null, [3,5,88,2])
在這裏,我們看到了一個有趣的現象,在Math.max中可以傳入數組
call&apply兩大作用:
改變this
借用其他對象的方法
改變this
如何實現Function.prototype.bind()
Function.prototype.bind = function(){
var self = this,
context = [].shift.apply(arguments);
args = [].slice.apply(arguments);
return function(){
return self.apply(context, [].concat.apply(args, [].slice.apply(arguments)))
};
}
//執行
var obj = {
name: 'yyh'
}
var func = function(a, b, c, d){
console.log(this.name);
}.bind(obj, 1, 2);
func(3, 4);
借用其他對象的方法
繼承的實現
var aFn = function(){
this.name = 'yyh'
}
var bFn = function(){
aFn.apply(this, arguments);
}
bFn.prototype.getName = function(){
return this.name
}
//執行
var b = new bFn();
console.log(b.getName())
能借用數組的方法,Obj.array.push, 需要滿足兩個條件
- Obj的屬性可存取
- length屬性可讀寫
var a = {c:3};
[].push.apply(a, [3,4,5])
console.log(a)