实现一个Bind和New

如何实现一个Bind

最简方式

通过给目标函数指定作用域来简单实现bind()方法

Function.prototype.bind = function(context){
    self = this;
    return function(){
        return self.apply(context,arguments);
    }
}
复制代码

考虑到函数科里化的情况

Function.prototype.bind = function(context){
    var args = Array.prototype.slice.call(arguments);
    self = this;
    return fucntion(){
        var innerArgs = Array.prototype.slice.call(arguments);
        var finalArgs = args.concat(innerArgs);
        return self.apply(context,finalArgs)
    }
}
复制代码

知识点:

函数科里化

function add (a,b,c){
    var i = a+b+c;
    console.log(i);
    return i;
}

var func = add.bind(undefined,100) ; // 给add()传了第一个参数a
fucn(1,2); // 103,继续传入b和c

var func2 = func.bind(undefined,200);//给func2传入第一个参数,也就是b, 此前func已有参数a=100
func2(10);//310,继续传入c,100+200+10
复制代码

这是高阶函数的一种特殊用法

柯里化是指这样一个函数(假设叫做createCurry),他接收函数A作为参数,运行后能够返回一个新的函数。并且这个新的函数能够处理函数A的剩余参数。

Array.prototype.slice.call(arguments)

Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组

var a={length:2,0:'first',1:'second'};
Array.prototype.slice.call(a);//  ["first", "second"]
  
var a={length:2};
Array.prototype.slice.call(a);//  [undefined, undefined]
复制代码

首先,slice有两个用法,一个是String.slice,一个是Array.slice

第一个返回的是字符串,第二个返回的是数组,这里我们看第2个。

Array.prototype.slice.call(arguments)能够将arguments转成数组,那么就是arguments.toArray().slice()。

Array.prototype.slice.call(arguments,1)

slice返回一个数组,该方法只有一个参数的情况下表示除去数组内的第一个元素。这里是去掉函数自己的方法名

obj = {
    a1:function(){}
}
即去掉a1,只取参数。
复制代码

考虑到构造函数的情况

Function.prototype.bind = function(context){
  var args = Array.prototype.slice(arguments, 1),
  self = this,
  F = function(){},
  bound = function(){
      var innerArgs = Array.prototype.slice.call(arguments);
      var finalArgs = args.concat(innerArgs);
      return self.apply((this instanceof F ? this : context), finalArgs);
  };

  F.prototype = self.prototype;
  bound.prototype = new F();
  retrun bound;
};
复制代码

通过设置一个中转构造函数F,使绑定后的函数与调用bind()的函数处于同一原型链上,用new操作符调用绑定后的函数,返回的对象也能正常使用instanceof,因此这是最严谨的bind()实现

如何实现一个New

  1. 新生成了一个对象
  2. 新对象隐式原型链接到函数原型
  3. 调用函数绑定this
  4. 返回新对象

核心代码

首先写一个父类

function Person(name,age){
    this.name = name;
    this.age = age;
}
复制代码

自定义一个New函数

//通过分析原生的new方法可以看出,在new一个函数的时候,
// 会返回一个func同时在这个func里面会返回一个对象Object,
// 这个对象包含父类func的属性以及隐藏的__proto__
function New(f) {
    //返回一个func
    return function () {
        var o = {"__proto__": f.prototype};
        f.apply(o, arguments);//继承父类的属性

        return o; //返回一个Object
    }
}
复制代码

优先级问题

优先级由高到低:==小括号(xxx) > 属性访问. > new foo() > foo()==      

属性访问.和new foo() 同为18级,按从左到右先访问的顺序    

new foo() 和 new foo 的区别在于new的有参和无参方式,有参18级大于无参17级。      

综合考量基础的面试题

根据上面面试题整理的知识点:

函数的方法

        function User(name) {
			var name = name; //私有属性
			this.name = name; //公有属性
			function getName() { //私有方法
				return name;
			}
		}
		User.prototype.getName = function() { //公有方法
			return this.name;
		}
		User.name = 'Wscats'; //静态属性
		User.getName = function() { //静态方法
			return this.name;
		}
		var Wscat = new User('Wscats'); //实例化
复制代码
  • 调用公有方法,公有属性,我们必需先实例化对象,也就是用 new 操作符实化对象,就可构造函数实例化对象的方法和属性,并且公有方法是不能调用私有方法和静态方法的
  • 静态方法和静态属性就是我们无需实例化就可以调用
  • 而对象的私有方法和属性,外部是不可以访问的

转载于:https://juejin.im/post/5c9c2c0f5188251d17547910

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值