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