new
//创建一个对象
//将构造函数的作用域给新对象
//执行构造函数中的代码
//返回新对象
function _new(context,...args){
if(typeof context != 'function'){
throw 'context must be a function'
}
//实例对象
let obj = new Object()
//实例对象的 __proto__属性 指向构造函数的原生对象
obj.__proto__ = Object.create(context.prototype)
//apply将实例对象作为第一对象,实例对象作为函数上下文对象,
//可以直接访问原生对象的属性,通过实例对象就可以访问到,因为this指向实例对象
//保存返回值
res = context.apply(obj,[...args])
//判断是否是引用对象
let isObject = typeof res === 'object' &&typeof res !== null
let isFunction = typeof res === 'function'
//判断返回值,如果是一个对象Object 那就返回该对象作为整个表达式;如果是非对象,就忽略返回值,直接返回新创建的对象
return isObject || isFunction ? res :obj
}
call
Function.prototype.call = function(context,...args){
//判断传入是狗有参数,无指向全局对象window,有指向context
var context =context || window
//为context仿造一个函数this中的fn
context.fn = this
//eval() 来执行一个算术表达式:因为 JavaScript 可以自动为算术表达式求值。
//result来保存eval执行函数(参数)的结果
var result = eval('context.fn(...args')
//删掉仿造的方法
delete context.fn
return result
}
apply
Function.prototype.apply = function(context,args){
//apply和call不同的就是参数形式,apply是数组,所以直接用args表示,call用..args
let context = context || window
context.fn = this
let res = eval('context.fn(...args)')
delete context.fn
return res
}
bind
Function.prototype.bind = function (context, ...args) {
// 异常处理
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
// 保存this的值,它代表调用 bind 的函数
//self保存原来的对象或者是全局对象
var self = this;
//创建新的函数
var fNOP = function () {};
//判断是否是new出来的实例对象,如果是指向构造函数
//不是的话,整个函数的作用就是将this指向参数的第一对象,改变函数上下文状态
var fbound = function () {
self.apply(this instanceof self ?
this :
context, args.concat(Array.prototype.slice.call(arguments)));//实现借用Array的slice切割参数
}
//新函数指向全局对象或者原来调用的对象,eg:model:{name:'ll'},model.name,model是this
fNOP.prototype = this.prototype;
//fbfound指向FNOP的构造函数
fbound.prototype = new fNOP();
//fbound->FNOP->全局对象->原生对象
return fbound;
}