一、new 操作
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
(3) 执行构造函数中的代码(为这个新对象添加属性) ;
(4) 返回新对象。
function Person(name,age){
this.name = name ;
this.age = age ;
}
function rewriteNew(sup,...param){
//1.创建新对象
var obj = {};
//2.将空对象作为 this,调用构造函数并传入参数
var result = sup.call(obj,...param);
//3.将该对象__proto__指向构造函数原型对象,实现继承
obj.__proto__ = sup.prototype;//Object.setPrototypeOf(obj,sup.prototype)
//4.如果构造函数返回值为对象或者函数,则返回该对象或者函数,否则返回创建的新对象obj
return typeOf result === "object" || typeOf result === "function"?result:obj
};
var jack = rewriteNew(Person,'jack',12);
console.log(jack);//{name:jack,age:12};
二、call、apply、bind
作用:都是修改this指向
差异:
(1)call与apply 参数不同:
// call 从第二个。。。依次列出参数 apply 第二个参数是数组
obj.myFun.call(db,'成都','上海');
obj.myFun.apply(db,['成都','上海']);
(2)call、apply 与bind 差异为call、apply 修改this指向并且执行函数,bind只修改this指向但不立即执行函数,bind参数与call 一致
obj.myFun.call(db)
obj.myFun.apply(db);
obj.myFun.bind(db)();
1、手写一个call 方法
es5 写法
Function.prototype.myCall1 = function(context){
context = context || 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+')')
return result;
}
es6 写法
Function.prototype.myCall2 = function(context){
context = context || window
context.fn = this;
var args = [];
for(var i = 1,len = arguments.length; i < len; i++){
args.push(arguments[i])
}
var result = context.fn(...args);
delete context.fn
return result;
}
2、apply
Function.prototype.myApply = function (context,arr){
var context = context || window;
context.fn = this;
if(!arr){
result = context.fn()
}else {
var args = [];
for(var i = 1, len = arr.length; i <len; i++){
args.push('arr['+i+']');
}
result = eval('context.fn('+args+')')
}
delete context.fn;
return result;
}
3、bind
Function.prototype.mybind = function(context){
let that = this;
let args1 = Array.prototype.slice.call(arguments,1);
let bindFn = function(){
let args2 = Array.prototype.slice.call(arguments);
return that.apply(this instanceof bindFn?this:context,args1.concat(args2));
}
let Fn = function(){};
Fn.prototype = this.prototype;
bindFn.prototype = new Fn();
return bindFn;
}