bind
- bind方法可以绑定this指向、参数
- bind方法返回一个绑定后的函数 (高阶函数)
Function.prototype.bind = function (context) {
let that = this;
let bindArge = Array.prototype.slice.call(arguments, 1);
return function (){
let args = Array.prototype.slice.call(arguments);
that.apply(context, bindArge.concat(args));
}
}
let obj = {
name: 1
}
function fn(name, age) {
console.log(this.name, name, age)
}
let bindFn = fn.bind(obj, '猪');
bindFn(8) //1 '猪' 8
- 如果绑定的函数被new,当前的函数this就是当前的实例
- new 出来的的结果,可以找到原有类的原型
Function.prototype.bind = function (context) {
let that = this;
let bindArge = Array.prototype.slice.call(arguments, 1);
function Fn() {};
function fBind() {
let args = Array.prototype.slice.call(arguments);
that.apply(this instanceof fBind ? this : context, bindArge.concat(args));
}
Fn.prototype = this.prototype;
fBind.prototype = new Fn();
return fBind;
}
let obj = {
name: 1
}
function fn(name, age) {
this.name = '自己的';
console.log(this) //fn { name: '自己的' }
console.log(this.name, name, age) //自己的 猪 9
}
fn.prototype.flag = '2'
let bindFn = fn.bind(obj, '猪');
let instance = new bindFn(9);
console.log(instance.flag); // 2
new
- 创建一个实例对象,并且把实例的__proto__指向给这个类的原型对象
- 如果当前的构造函数返回的是一个引用类型,需要把这个引用类型返回
- 如果当前的构造函数不是引用类型,返回这个实例对象
function MockNew(){
let Constructor = [].shift.call(arguments);
let obj = {};
obj.__proto__ = Constructor.prototype;
let r = Constructor.apply(obj, arguments);
return r instanceof Object ? r : obj;
}
function Animal(type) {
this.type = type;
return 1
}
Animal.prototype.say = function (){
console.log('say');
}
let animal = MockNew(Animal, '哺乳类');
console.log(animal); //Animal { type: '哺乳类' }
call
- 可以改变当前函数的this指向
- 当前函数执行
Function.prototype.call = function (context){
context = context ? Object(context) : window;
context.fn = this;
let args = [];
for (let i = 1; i < arguments.length; i++) {
//利用toString方法
args.push('arguments[' + i + ']');
}
let r = eval('context.fn(' + args + ')');
delete context.fn;
return r;
}
function fn1() {
console.log(this, arguments);
}
function fn2() {
console.log(this, 2);
}
fn1.call(fn2) //fn []
fn1.call.call(fn2) // window 2
fn1.call.call.call(fn2) // window 2
如果是一个call会让call方法执行,并且把call中的this改变成fn2
如果是多个call会让call方法执行,并且把call中的this改变成window
apply
Function.prototype.apply = function(context, args){
context = context ? Object(context) : window;
context.fn = this;
if (!args) {
return context.fn();
}
let r = eval('context.fn('+ args + ')');
delete context.fn;
return r;
}
function fn1() {
console.log(this, arguments);
}
fn1.apply('hello', [1, 2, 3, 4]) // hello [1, 2, 3, 4]
`