链式调用
- 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 = Windows
- }
- 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 = Windows
- }
- 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'))
来源: http://www.bubuko.com/infodetail-3669222.html