链式调用 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‘))