9.10,,,实现new instanceof apply call 高阶函数,偏函数,柯里化

链式调用

let obj = {
  a: 0,
  f1() {
    this.a += 1
    console.log(this.a)
    return this
  },
  f2() {
    this.a += 2
    console.log(this.a)
    return this
  },
  f3() {
    this.a += 3
    console.log(this.a)
    return this
  }
}
// obj.f1().f1().f1()//1 2 3
// obj.f2().f2().f2()//5 7 9
// obj.f3().f3().f3()//12 15 18
obj.f1().f2().f3()//1 3 6

  

new

function Person(name) {
  this.name = name
}
let p  = new Person('name')
function New() {
  let obj = {  }
  obj.__proto__ = Person.prototype
  Person.apply(obj,Array.prototype.slice.call(arguments, 1))
  return typeof obj === 'object' ? obj : {}
}
let p1 = New(Person,'name')
console.log(p1)
//Person {name: "name"}
//name: "name"
//__proto__:
//constructor: ƒ Person(name)
//__proto__: Object
function New1(f) {
  //返回一个func
  return function () {
      var o = {"__proto__": f.prototype};
      f.apply(o, arguments);//继承父类的属性
      return o; //返回一个Object
  }
}
var p2 = New1(Person)("Jack",25);
console.log(p2)

// 判断Test 是否是被new执行的
function Test() {
  console.log(new.target)
}
Test() // undefined
new Test() // [Function: Test] 也就是 new.target === Test
intanceof


function Instanceof(obj,fn) {
  if(typeof fn !== 'function'){
    throw new Error('instance error')
  }
  if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) {
    return false
  }
  let type = fn.prototype  //原型对象
  while (obj.__proto__) { //对象原型
    if (obj.__proto__ === type) {
      return true
    }
    obj = obj.__proto__
  }
  return false
}
console.log(Instanceof([],Array))//true
console.log(Instanceof([],Function))//false
console.log([] instanceof Function)//false
//call apply

Function.prototype.Call(context) {
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  context.fn = this //调用Call的那个函数
  let args = [...argments].slice(1)
  context.fn(...agrs) //apply就直接参数数组参数
  delete context.fn
}
//例子
Function.prototype.Call = function (context) {
  console.log(context) //{ name: 'Tom1' }
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  console.log(context) //{ name: 'Tom1' }
  context.fn = this
  console.log(this,context.fn) //[Function: say] [Function: say]
  let args = [...arguments].splice(1)
  context.fn(...args)
  console.log(args) //[ 1 ]
  delete context.fn
}
let Person1 = {
  name: 'Tom',
  say(age) {
      //console.log(this)
      console.log(`我叫${this.name}+${age}`)
  }
}
// 先看代码执行效果
Person1.say() //我叫Tom 
Person2 = {
  name: 'Tom1'
}
Person1.say.call(Person2) //我叫Tom1
Person1.say.Call(Person2,1)

//例2扩展用法
function Doctor(name){
  this.name = name;
  this.say = function(){
      console.log(this.name)
  }
}
function Stephen(name){
  //当前函数内的this指向函数Son的实例化对象
  //在执行Stephen时执行Doctor,同时将Doctor内的this改变成Stephen的this
  Doctor.Call(this,name)
}
 var doctor = new Doctor("Doctor")
 doctor.say();       //Doctor
 var stephen = new Stephen("Stephen Strange")
// // 在Stephen中并没有say方法,但是因为在new Stephen时,执行了Doctor,
// // 并将Doctor中的this指向Stephen的this,
// // 那么在new Stephen后,得到的实例,也具有了Doctor内的属性和方法
 stephen.say();      //Stephen Strange



//bind
//高阶函数
//JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
function add(x, y, f) {
    return f(x) + f(y);
}
console.log(add(-5, 6, Math.abs)) //11
//偏函数
//固定一个或者几个参数,返回一个新的函数,接收剩下的参数
function add(a,b){ //固定参数
  return a + b;
}
//生产偏函数的工厂
function partial(fn,a){
  return function(b){
      return fn(a,b);
  }
}
var parAdd = partial(add,1);//变量parAdd接受返回的新函数
console.log(parAdd(2));//在调用的时候传入剩余的参数
console.log(parAdd(3));//在调用的时候传入剩余的参数
console.log(parAdd(4));//在调用的时候传入剩余的参数
//柯里化sum(1)(2)(3)...
//把接收多个参数的函数转换成多个接收一个参数的函数----可以延迟执行 ,bind也是
//因为没满足原参数个数就不会返回结果
//辅助函数
function sub_curry(fn) {
  let args = [...arguments].slice(1)
  return function () {
    return fn.apply(this.args.concat([...arguments]))
  }
}
function curry(fn,length){
   length = length || fn.length//Function.prototype.length 属性,就是为了告诉你这个函数定义了几个参数。
  return function() {
    if(arguments.length < length) {
      let next = [fn].concat(...arguments) //包含fn,因为重复调辅助函数
    return length - arguments.length > 0 
      ? curry(sub_curry.apply(this, combined), length - arguments.length)
      : sub_curry.call(this, combined );
      
    }else {
       return fn.apply(this,arguments) //拿到了原函数的所有参数
    }
  }
}
var fn = function(a, b, c) { return [a, b, c]; };
 curry(fn)('a')('a','a')
console.log( curry(fn)('a','a')('a'))
原文地址:https://www.cnblogs.com/zjj-study/p/13645779.html