手写 js 中 new call apply bind

1、手写new

function Student (name, age){
    this.name = name;
    this.age = age;
}
Student.prototype.like = function () {
	console.log('读书');
}
function MyNew(){
    const obj = Object.create({});
    const [constructor, ...args] = [...arguments];
    obj.__proto__ = constructor.prototype;
    const result= constructor.apply(obj, args); // 判断构造函数是否存在返回值
    if (result && ( typeof (result) == "object") || typeof(result) == "function") {
		return result;
	}
    return obj;
}
var  myName = MyNew(Student , '张三', 46)
console.log(myName.name)   // 张三
console.log(myName.age)  // 46
myName.like() // 读书

上面代码解释

1、创建一个新的对象,并返回。
2、截取传入MyNew函数的第一个参数, 其实就是创建构造函数。
3、将第一个参数的prototype与要返回的对象建立关联。
4、使用apply,改变构造函数的this指向,使其指向新对象,这样,obj就可以访问到构造函数中的属性了。
5、构造函数如果return 出一个对象或函数,那么new 实例,只能访问到 这个对象属性,所以判断一下

2、手写call

Function.prototype.myCall = function (context) {
// 判断有没有传进来对象, 没有默认就是  windows
	context= context ? Object(context) : windows;
	//  属性唯一 , 防止属性名冲突
	var fn = Symbol();
	context[fn] = this;
	const args = [...arguments].slice(1);
	// call  参数是字符串 所以需要 ... 运算符
	const result = context[fn](...arg);
	delete context[fn];
	return result;
}

var obj = {
  name: "张三"
};

function person (sex, weight) {
  console.log(this.name, sex, weight);
}
person.myCall(obj, '李四', 18);

3、手写 apply

Function.prototype.myApply= function(context, arr) {
  context = context ? Object(context) : window;
  let fn = Symbol();
  context[fn] = this;
  // 参数有没有
  let result = arr ? context[fn](...arr) : context[fn]();
  delete context[fn];
  return result;
};

4、手写 bind

Function.prototype.bind2 = function(context) {
  if (typeof this !== "function") {
    throw new Error(
      "Function.prototype.bind - what is trying to be bound is not callable"
    );
  }
  var self = this;
  var args = Array.prototype.slice.call(arguments, 1);

  var fBound = function() {
  // 接收 额外 的参数
    var innerArgs = Array.prototype.slice.call(arguments);
    // 当 被 new 时, this 指向当前 实例, 不再指向 绑定的 对象
    return self.apply(
      this instanceof fNOP ? this : context,
      args.concat(innerArgs)
    );
  };
	// 绑定原型 , 当 返回的 fBound 被当初 构造函数, 其实就是 被调用的函数当作 构造函数, 所以 返回的函数要 继承 被调用函数的 原型
  var fNOP = function() {};
  fNOP.prototype = this.prototype;
  fBound.prototype = new fNOP();
  return fBound;
};
使用
function foo(name) {
this.name = name;
}
var obj = {};
var bar = foo.myBind(obj);
bar('Jack');
console.log(obj.name);  // Jack

//  new bar  其实就是  new foo 

var alice = new bar('Alice');
console.log(obj.name);  // Jack
console.log(alice.name);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值