Git Product home page Git Product logo

Comments (28)

ettingshausen avatar ettingshausen commented on August 15, 2024 37

补充一个使用 apply 的例子。
比如求一个数组的最大值,使用 Math.max 函数,但是这个函数入参不支持数组,只能是将多个参数逐个传入,用逗号分隔。

let max = Math.max(1, 4, 8, 9, 0)

有了 apply,就可以这么调用:

let arr = [1, 4, 8, 9, 0];
let max = Math.max.apply(null, arr);

from blog.

fonice avatar fonice commented on August 15, 2024 34

2.借用别的对象的方法

Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象

我的理解是 Person1 的 this 变成 Person2的this,并执行一遍Person1函数

Person2就多了一个name属性

from blog.

Fang0408 avatar Fang0408 commented on August 15, 2024 11

ES6里面的call还能用解构来传参
const f = function (a, b, c) { console.log(a, b, c) } const arr = [1, 2, 3] f.call(null, ...arr)

from blog.

izayoi-hibiki avatar izayoi-hibiki commented on August 15, 2024 7
if (!Function.prototype.bind) {
        Function.prototype.bind = function () {
            var self = this,                        // 保存原函数
                context = [].shift.call(arguments), // 保存需要绑定的this上下文
                args = [].slice.call(arguments);    // 剩余的参数转为数组
            return function () {                    // 返回一个新函数
                self.apply(context,[].concat.call(args, [].slice.call(arguments)));
            }
        }
    }

以上返回的函数体中的 self.apply(context,[].concat.call(args, [].slice.call(arguments))) 里第二个参数为啥是 [].concat.call(args, [].slice.call(arguments)), 它不就应该是 args 吗 ?
@lin-xin

同问

Function.prototype.binding = function () {
    let self = this;
    let context = [].shift.call(arguments);
    let args = [].slice.call(arguments);
    console.log('Function binding args', args);

    return function () {
        self.apply(context, [].concat.call(args, [].slice.call(arguments)))
    }
};

let obj = {
    a: 'a'
};

function f(b, c, d) {
    console.log(this.a, b, c, d)
}

f.binding(obj, 'b', 'c', 'd')('e');
f.binding(obj, 'b', 'c')('d', 'e');
f.binding(obj, 'b')('c', 'd', 'e');
f.binding(obj)('b', 'c', 'd', 'e');

输出:

Function binding args [ 'b', 'c', 'd' ]
a b c d
Function binding args [ 'b', 'c' ]
a b c d
Function binding args [ 'b' ]
a b c d
Function binding args []
a b c d

Process finished with exit code 0

从输出可以看出 argsf.binding 里除了第一个参数剩下所有的参数,而 [].slice.call(arguments)f.binding 后第二个括号里的参数, args 的 this 是 Function.prototype.binding[].slice.call(arguments) 的 this 是 f.binding(obj)()

from blog.

Kingwantfly avatar Kingwantfly commented on August 15, 2024 6

完美,讲的很好

from blog.

laclys avatar laclys commented on August 15, 2024 5

@Fang0408 直接f(...arr)不就得了

from blog.

devindo avatar devindo commented on August 15, 2024 4

补充一个使用 apply 的例子。
比如求一个数组的最大值,使用 Math.max 函数,但是这个函数入参不支持数组,只能是将多个参数逐个传入,用逗号分隔。

let max = Math.max(1, 4, 8, 9, 0)

有了 apply,就可以这么调用:

let arr = [1, 4, 8, 9, 0];
let max = Math.max.apply(null, arr);

Math.max(...[1,2,3])

from blog.

xsdream avatar xsdream commented on August 15, 2024 2

nice!

from blog.

Rudy24 avatar Rudy24 commented on August 15, 2024 1

@lin-xin 楼主这里有点问题吧 Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,
Person1.call(this), 按照理解应该是 把Person1函数中的this指向了Person2中的this

from blog.

leiyangs avatar leiyangs commented on August 15, 2024 1

豁然开朗

from blog.

DummyLIU avatar DummyLIU commented on August 15, 2024

good

from blog.

124design avatar 124design commented on August 15, 2024

nice!

from blog.

HiIcy avatar HiIcy commented on August 15, 2024

nice!

from blog.

ycshill avatar ycshill commented on August 15, 2024

var Person1 = function () {
this.name = 'linxin';
}
var Person2 = function () {
this.getname = function () {
console.log(this.name);
}
Person1.call(this);
}
var person = new Person2();
person.getname();
这个例子不是太理解,各位楼主有没有详细解答的

from blog.

web-display avatar web-display commented on August 15, 2024

在一定程度上Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象是成立的,那样子的话Person2就不能拥有自己的属性了,我的理解是Person1.call(this)执行完毕后讲Person1的属性复制到了Person2中

from blog.

ZhangzyGY avatar ZhangzyGY commented on August 15, 2024

nice!

from blog.

16slowly avatar 16slowly commented on August 15, 2024
if (!Function.prototype.bind) {
        Function.prototype.bind = function () {
            var self = this,                        // 保存原函数
                context = [].shift.call(arguments), // 保存需要绑定的this上下文
                args = [].slice.call(arguments);    // 剩余的参数转为数组
            return function () {                    // 返回一个新函数
                self.apply(context,[].concat.call(args, [].slice.call(arguments)));
            }
        }
    }

以上返回的函数体中的 self.apply(context,[].concat.call(args, [].slice.call(arguments))) 里第二个参数为啥是 [].concat.call(args, [].slice.call(arguments)), 它不就应该是 args 吗 ?
@lin-xin

from blog.

MontageD avatar MontageD commented on August 15, 2024

好文,赞

from blog.

montilloo avatar montilloo commented on August 15, 2024

Perfect!

from blog.

ChrisSong1994 avatar ChrisSong1994 commented on August 15, 2024

@lin-xin 楼主这里有点问题吧 Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,
Person1.call(this), 按照理解应该是 把Person1函数中的this指向了Person2中的this

返回的是一个函数,可以继续添加参数

from blog.

zqzq3 avatar zqzq3 commented on August 15, 2024

完全看不懂

from blog.

ximelly avatar ximelly commented on August 15, 2024
if (!Function.prototype.bind) {
        Function.prototype.bind = function () {
            var self = this,                        // 保存原函数
                context = [].shift.call(arguments), // 保存需要绑定的this上下文
                args = [].slice.call(arguments);    // 剩余的参数转为数组
            return function () {                    // 返回一个新函数
                self.apply(context,[].concat.call(args, [].slice.call(arguments)));
            }
        }
    }

以上返回的函数体中的 self.apply(context,[].concat.call(args, [].slice.call(arguments))) 里第二个参数为啥是 [].concat.call(args, [].slice.call(arguments)), 它不就应该是 args 吗 ?
@lin-xin

同问

from blog.

ximelly avatar ximelly commented on August 15, 2024
if (!Function.prototype.bind) {
        Function.prototype.bind = function () {
            var self = this,                        // 保存原函数
                context = [].shift.call(arguments), // 保存需要绑定的this上下文
                args = [].slice.call(arguments);    // 剩余的参数转为数组
            return function () {                    // 返回一个新函数
                self.apply(context,[].concat.call(args, [].slice.call(arguments)));
            }
        }
    }

以上返回的函数体中的 self.apply(context,[].concat.call(args, [].slice.call(arguments))) 里第二个参数为啥是 [].concat.call(args, [].slice.call(arguments)), 它不就应该是 args 吗 ?
@lin-xin

同问

Function.prototype.binding = function () {
    let self = this;
    let context = [].shift.call(arguments);
    let args = [].slice.call(arguments);
    console.log('Function binding args', args);

    return function () {
        self.apply(context, [].concat.call(args, [].slice.call(arguments)))
    }
};

let obj = {
    a: 'a'
};

function f(b, c, d) {
    console.log(this.a, b, c, d)
}

f.binding(obj, 'b', 'c', 'd')('e');
f.binding(obj, 'b', 'c')('d', 'e');
f.binding(obj, 'b')('c', 'd', 'e');
f.binding(obj)('b', 'c', 'd', 'e');

输出:

Function binding args [ 'b', 'c', 'd' ]
a b c d
Function binding args [ 'b', 'c' ]
a b c d
Function binding args [ 'b' ]
a b c d
Function binding args []
a b c d

Process finished with exit code 0

从输出可以看出 argsf.binding 里除了第一个参数剩下所有的参数,而 [].slice.call(arguments)f.binding 后第二个括号里的参数, args 的 this 是 Function.prototype.binding[].slice.call(arguments) 的 this 是 f.binding(obj)()

明白了 多谢!

from blog.

httol avatar httol commented on August 15, 2024
if (!Function.prototype.bind) {
        Function.prototype.bind = function () {
            var self = this,                        // 保存原函数
                context = [].shift.call(arguments), // 保存需要绑定的this上下文
                args = [].slice.call(arguments);    // 剩余的参数转为数组
            return function () {                    // 返回一个新函数
                self.apply(context,[].concat.call(args, [].slice.call(arguments)));
            }
        }
    }

以上返回的函数体中的 self.apply(context,[].concat.call(args, [].slice.call(arguments))) 里第二个参数为啥是 [].concat.call(args, [].slice.call(arguments)), 它不就应该是 args 吗 ?
@lin-xin

同问

Function.prototype.binding = function () {
    let self = this;
    let context = [].shift.call(arguments);
    let args = [].slice.call(arguments);
    console.log('Function binding args', args);

    return function () {
        self.apply(context, [].concat.call(args, [].slice.call(arguments)))
    }
};

let obj = {
    a: 'a'
};

function f(b, c, d) {
    console.log(this.a, b, c, d)
}

f.binding(obj, 'b', 'c', 'd')('e');
f.binding(obj, 'b', 'c')('d', 'e');
f.binding(obj, 'b')('c', 'd', 'e');
f.binding(obj)('b', 'c', 'd', 'e');

输出:

Function binding args [ 'b', 'c', 'd' ]
a b c d
Function binding args [ 'b', 'c' ]
a b c d
Function binding args [ 'b' ]
a b c d
Function binding args []
a b c d

Process finished with exit code 0

从输出可以看出 argsf.binding 里除了第一个参数剩下所有的参数,而 [].slice.call(arguments)f.binding 后第二个括号里的参数, args 的 this 是 Function.prototype.binding[].slice.call(arguments) 的 this 是 f.binding(obj)()

明白了 多谢!

这个是标准的闭包写法,函数嵌套函数的时候,被嵌套的函数的作用域链是单独的,而且每次执行外部函数时,这个作用域链总是会生成新的链,像this和arguments都不会和外部函数共享,也是单独的,比如嵌套函数想拿到外部的arguments和this需要在嵌套函数外面用变量做存储才可以,类似let self = this,let args = arguments。例子中嵌套函数的arguments就是自己函数的,而不是外部函数的。

Function.prototype.binding = function () {
    let self = this;
    let context = [].shift.call(arguments);
    let args = [].slice.call(arguments);
    console.log('Function binding args', args);

    return function () {console.log('innerFunc',arguments);
        self.apply(context, [].concat.call(args, [].slice.call(arguments)))
    }
};

let obj = {
    a: 'a'
};

function f(b, c, d) {
    console.log(this.a, b, c, d)
}

f.binding(obj, 'b', 'c', 'd')('e');
f.binding(obj, 'b', 'c')('d', 'e');
f.binding(obj, 'b')('c', 'd', 'e');
f.binding(obj)('b', 'c', 'd', 'e');
Function binding args (3) ["b", "c", "d"]
innerFunc Arguments ["e", callee: ƒ, Symbol(Symbol.iterator): ƒ]
Function binding args (2) ["b", "c"]
innerFunc Arguments(2) ["d", "e", callee: ƒ, Symbol(Symbol.iterator): ƒ]
Function binding args ["b"]
innerFunc Arguments(3) ["c", "d", "e", callee: ƒ, Symbol(Symbol.iterator): ƒ]
VM1135:5 Function binding args []
innerFunc Arguments(4) ["b", "c", "d", "e", callee: ƒ, Symbol(Symbol.iterator): ƒ]

from blog.

1793523411 avatar 1793523411 commented on August 15, 2024

懂了,真棒!!!

from blog.

haohao3308 avatar haohao3308 commented on August 15, 2024
if (!Function.prototype.bind) {
        Function.prototype.bind = function () {
            var self = this,                        // 保存原函数
                context = [].shift.call(arguments), // 保存需要绑定的this上下文
                args = [].slice.call(arguments);    // 剩余的参数转为数组
            return function () {                    // 返回一个新函数
                self.apply(context,[].concat.call(args, [].slice.call(arguments)));
            }
        }
    }

以上返回的函数体中的 self.apply(context,[].concat.call(args, [].slice.call(arguments))) 里第二个参数为啥是 [].concat.call(args, [].slice.call(arguments)), 它不就应该是 args 吗 ?
@lin-xin

同问

Function.prototype.binding = function () {
    let self = this;
    let context = [].shift.call(arguments);
    let args = [].slice.call(arguments);
    console.log('Function binding args', args);

    return function () {
        self.apply(context, [].concat.call(args, [].slice.call(arguments)))
    }
};

let obj = {
    a: 'a'
};

function f(b, c, d) {
    console.log(this.a, b, c, d)
}

f.binding(obj, 'b', 'c', 'd')('e');
f.binding(obj, 'b', 'c')('d', 'e');
f.binding(obj, 'b')('c', 'd', 'e');
f.binding(obj)('b', 'c', 'd', 'e');

输出:

Function binding args [ 'b', 'c', 'd' ]
a b c d
Function binding args [ 'b', 'c' ]
a b c d
Function binding args [ 'b' ]
a b c d
Function binding args []
a b c d

Process finished with exit code 0

从输出可以看出 argsf.binding 里除了第一个参数剩下所有的参数,而 [].slice.call(arguments)f.binding 后第二个括号里的参数, args 的 this 是 Function.prototype.binding[].slice.call(arguments) 的 this 是 f.binding(obj)()

既然 args已经 转化为数组了那最后的 :
`self.apply(context, [].concat.call(args, [].slice.call(arguments)))`
写成:
`self.apply(context, args.concat([].slice.call(arguments)))`
不是更方便
为什么还要调用一次call()呢

from blog.

SolitaryBirdDeadWood avatar SolitaryBirdDeadWood commented on August 15, 2024
    let arr1 = [1, 2, 7, 5, 6];
    let arr2 = [4, 7, 5, 4, 6, 8, ]
    Array.prototype.push.apply(arr1, arr2)

还有添加

from blog.

SolitaryBirdDeadWood avatar SolitaryBirdDeadWood commented on August 15, 2024

在Person2中的 call 将Person1的指向改为 Person2中的实例 Person1 的 this.name 相当于写在了 Person2中

from blog.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.