看了微信公众号【前端大全】的文章,学习一下
console.log("====================模拟call测试====================");
//模拟call实现 apply的实现类似call 函数定义为function(context,arr)
//1.改变this指向(第一个参数为null时,默认是window) 2.传入参数 返回结果 3.执行函数
Function.prototype.call2 = function(context){
var context = context || window;
context.fn = this; //把要执行的函数 作为context对象的方法执行 执行完再删除此方法
var args = [];
for(var i=1; i<arguments.length; i++){
args.push('arguments[' + i + ']');
}
console.log(Array.isArray(arguments)); //false
console.log(Array.isArray(Array.prototype.slice.call(arguments))); //true
console.log("args: ");
console.log(args);
console.log(args.join(","));
console.log(args.toString());
console.log('context.fn(' + args + ')'); //context.fn(arguments[1],arguments[2])
var result = eval('context.fn(' + args + ')'); //必须使用eval执行 才能将数组中的参数分开
//var result = context.fn(args.join(","));//这种方式传进的参数是一个由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
}
}
console.log(bar.call2(null));
//2 {age:undefined,name:undefined,value:2}
console.log(bar.call2(obj,"kevin",18));
//1 {age:undefined,name:undefined,value:1}
console.log("====================模拟bind测试====================");
//bind 模拟实现
//1可以传入参数 2返回一个函数
//当bind返回的函数作为构造函数的时候,bind时指定的this会失效 但传入的参数依然有效
Function.prototype.bind2 = function(context){
if(typeof this != "function"){
throw new Error("what is trying to be bound is not a function");
}
var self = this;
var args = Array.prototype.slice.call(arguments,1);
var fNOP = function(){};//临时构造函数
var fbound = function(){
self.apply(this instanceof self?this:context, //判断是否是用【bind返回的构造函数生成的实例对象】.【方法】的形式调用
args.concat(Array.prototype.slice.call(arguments))
);
}
fNOP.prototype = this.prototype;
fbound.prototype = new fNOP();
return fbound;
};
var value = 2;
var foo = {
value : 1
};
function bar(name,age){
this.habit = 'shopping';
console.log(this.value);
console.log(name);
console.log(age);
}
bar.prototype.friend = "kevin";
var bindFoo = bar.bind2(foo,"daisy");
var obj = new bindFoo("18");
//undefined
//daisy
//18
console.log(obj.habit);
console.log(obj.friend);
//shopping
//kevin
console.log("=====================模拟new测试=======================");
//new 做的事情:(1)新建一个对象,对象原型是构造函数原型对象 (2)将参数传入构造函数中 执行 (3) 返回新建对象
function objectFactory(){
var obj = new Object();
Constructor = [].shift.call(arguments); //取出第一个参数
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
return typeof ret == 'object'?ret:obj;
}
function Otaku(name,age){
this.strength = 60;
this.age = age;
//若返回对象 则无法获取printProperties函数
/*return {
name:name,
habit:"Games"
};*/
}
Otaku.prototype.printProperties = function (){
console.log("name: " + this.name + "; age: "
+ this.age + "; strength: " + this.strength + "; habit: " + this.habit);
};
var testObj = objectFactory(Otaku,"Kevin","18");
console.log(testObj);
testObj.printProperties(); //name:undefined;age:18;strength:60;habit:undefined