前端必须会的手写函数篇(一)

124 阅读1分钟

call

call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。

var foo = {
    value: 1
};

function bar() {
    console.log(this.value);
}

bar.call(foo); // 1

call改变了this的指向,此时的this指向全局window

简单模拟实现

function foo() {
	value : 1;
	bar: function() {
		console.log(this.value)
	}
}
foo.bar()
// 第一版
Function.prototype.call2 = function(context) {
    // 首先要获取调用call的函数,用this可以获取
    context.fn = this;	// 调用的时候才去讲this进行赋给上下文
    context.fn();
    delete context.fn;
}

// 测试一下
var foo = {
    value: 1
};

function bar() {
    console.log(this.value);
}

bar.call2(foo); // 1

call 函数还能给定参数执行函数

// 第二版
思路:从argument中去拿到参数的信息,然后传到调用的方法作用域中去
Function.prototype.call2 = function(context) {
    // 首先要获取调用call的函数,用this可以获取
    context.fn = this;	// 调用的时候才去讲this进行赋给上下文
    var arg = []
    // 将所有的atguments中的值进行动态的遍历
    for(let i = 1; i < arguments.length; i++) {
    	args.push('arguments['+ i +']')
    }
    eval('context.fn(' + args +')')		// args 会自动调用 Array.toString() 这个方法。	进行拼接
    context.fn();
    delete context.fn;
}

var foo = {
    value: 1
};

function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}

bar.call2(foo, 'kevin', 18); 
// kevin
// 18
// 1
// 第三版
Function.prototype.call2 = function (context) {
    var context = context || window;		// 当函数空调的时候,传入的值为undefined,此时需要指向window
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;		// 调用完的对象是能够进行返回的
}

// 测试一下
var value = 2;

var obj = {
    value: 1
}

function bar(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}

bar.call2(null); // 2

console.log(bar.call2(obj, 'kevin', 18));
// 1
// Object {
//    value: 1,
//    name: 'kevin',
//    age: 18
// }
call函数的实现:
Function.prototype.apply = function(context, arr) {
	var context = Object(context) || window;
	context.fn = this;
	
	var result;
	if(!arr) {
		result = context.fn();
	} else {
		var args = []
		for(let i =0;i< arr.length; i++) {
			args.push('arr['+ i +']')
		}
		result = eval('context.fn('+args+')')
	}
	delete context.fn();
	return result;
}