1+ <!DOCTYPE html>
2+ < html >
3+
4+ < head >
5+ < meta charset ="UTF-8 ">
6+ < title > js函数的call和apply方法</ title >
7+ < style type ="text/css ">
8+ h1 {
9+ text-align : center;
10+ }
11+
12+ pre {
13+ font-size : 16px ;
14+ }
15+ </ style >
16+ </ head >
17+
18+ < body >
19+ < h1 > JS函数的call和apply与bind方法</ h1 >
20+ < hr />
21+
22+ < pre >
23+ 在 JavaScript 中,call、apply 和 bind 是函数对象的三个内置方法,用于显式地设置函数执行时的 this 上下文。它们都属于 Function.prototype,因此所有函数都可以使用。
24+
25+ 一、call、apply 和 bind的共同点
26+ 1.都可以改变函数内部 this 的指向。
27+ 2.第一个参数都是要绑定给 this 的对象(如果传入 null 或 undefined,在非严格模式下会默认指向全局对象,如浏览器中的 window)。
28+
29+
30+ 二、call、apply 和 bind的区别
31+ < table border ="1 " cellpadding ="10 " cellspacing ="0 " style ="margin: auto; ">
32+ < tr > < th > 方法</ th > < th > 是否立即执行</ th > < th > 参数传递方式</ th > < th > 返回值</ th > </ tr >
33+ < tr > < td > call</ td > < td > ✅ 立即执行</ td > < td > 逐个参数传递 func.call(thisArg, arg1, arg2, ...)</ td > < td > 函数执行结果</ td > </ tr >
34+ < tr > < td > apply</ td > < td > ✅ 立即执行</ td > < td > 以数组形式传递参数 func.apply(thisArg, [arg1, arg2, ...])</ td > < td > 函数执行结果</ td > </ tr >
35+ < tr > < td > bind</ td > < td > ❌ 不立即执行</ td > < td > 逐个参数传递(可预设)func.bind(thisArg, arg1, arg2, ...)</ td > < td > 返回一个新函数</ td > </ tr >
36+ </ table >
37+
38+ 三、call、apply 和 bind的语法与示例
39+ 1. call
40+ 语法:
41+ func.call(thisArg, arg1, arg2, ...)
42+ 示例:
43+ function greet(greeting, punctuation) {
44+ console.log(`${greeting}, ${this.name}${punctuation}`);
45+ }
46+ const person = { name: 'Alice' };
47+ greet.call(person, 'Hello', '!'); // 输出: Hello, Alice!
48+
49+
50+ 2. apply
51+ 语法:
52+ func.apply(thisArg, [argsArray])
53+ 示例:
54+ greet.apply(person, ['Hi', '?']); // 输出: Hi, Alice?
55+
56+ 常用于将数组作为参数传给函数,例如:
57+ const numbers = [1, 2, 3, 4];
58+ const max = Math.max.apply(null, numbers); // 等价于 Math.max(1,2,3,4)
59+
60+
61+ 3. bind
62+ 语法:
63+ const newFunc = func.bind(thisArg, arg1, arg2, ...);
64+ 特点:
65+ 1.返回一个新函数,其 this 被永久绑定(即使再用 call/apply 也无法改变)。
66+ 2.可用于预设部分参数(柯里化)。
67+ 示例:
68+ const boundGreet = greet.bind(person, 'Hey');
69+ boundGreet('!'); // 输出: Hey, Alice!
70+
71+ 典型用途:
72+ 1.事件处理中绑定 this
73+ 2.创建具有固定上下文的回调函数
74+ class Button {
75+ constructor(name) {
76+ this.name = name;
77+ }
78+ handleClick() {
79+ console.log(`Button ${this.name} clicked`);
80+ }
81+ }
82+
83+ const btn = new Button('Submit');
84+ document.getElementById('myBtn').addEventListener('click', btn.handleClick.bind(btn)); // 绑定 this,避免在事件回调中丢失
85+
86+
87+ 四、总结口诀
88+ “Call 一个个,Apply 用数组,Bind 不执行只返回。”
89+ call 和 apply 立即调用,区别在于参数形式;
90+ bind 返回绑定后的新函数,常用于延迟执行或固定上下文。
91+
92+ 每一个函数都包含两个非继承而来的方法:call、apply。这俩个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
93+
94+ call、apply的用途之一就是传递参数,但事实上,它们真正强大的地方式能够扩充函数赖以运行的作用域。
95+ 使用call()、aplly()来扩充作用域的最大好处就是对象不需要与方法有任何耦合关系。
96+ call方法简单的实现。
97+
98+
99+ </ pre >
100+ </ body >
101+ < script type ="text/javascript " charset ="UTF-8 ">
102+
103+ //call apply bind 的最简调用
104+ {
105+ // 任意一个函数都包含call和apply和bind方法
106+ function sum ( x , y ) {
107+ return x + y ;
108+ }
109+
110+ // call的语法:function.call(thisArg, arg1, arg2, ...);
111+ var result1 = sum . call ( null , 10 , 20 ) ; //用call方法把sum函数绑定到this【Fn1】函数中(这俩个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。)
112+ console . log ( 'call的调用:' , result1 ) ;
113+
114+
115+ // apply的语法:function.apply(thisArg, [argsArray]);
116+ var result2 = sum . apply ( null , [ 100 , 200 ] ) ; //apply方法和call方法差不多,把另一个方法绑定到当前方法中,【注:apply里面是 数组,这是它和 call方法的区别】
117+ console . log ( 'apply的调用:' , result2 ) ;
118+
119+
120+ // bind的语法:function.bind(thisArg, arg1, arg2, ...);
121+ var result3 = sum . bind ( null , 30 , 40 ) ; //bind方法创建一个新的函数,在调用时this值被绑定到传入的第一个参数上,后续参数作为预设参数传递给函数。
122+ console . log ( 'bind的调用:' , result3 ( ) ) ; // 注:bind调用绑定后返回的是一个函数,需要加括号执行调用。
123+ }
124+
125+ //call apply 简单的用法:绑定一些函数或一个作用域中,用于传递参数和调用
126+ {
127+ // 任意一个函数都包含call和apply和bind方法
128+ function sum ( x , y ) {
129+ console . log ( '调用时的this指向:' , this ) ; // 查看this指向
130+ return x + y ;
131+ }
132+
133+ function Fn1 ( num1 , num2 ) {
134+ return sum . call ( this , num1 , num2 ) ; //用call方法把sum函数绑定到this【Fn1】函数中(这俩个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。)
135+ }
136+
137+ function Fn2 ( num1 , num2 ) {
138+ this . add = 666 ; // 给this对象添加一个属性,用于验证this指向
139+ return function ( ) {
140+ return sum . apply ( this , [ num1 , num2 ] ) ; //apply方法和call方法差不多,把另一个方法绑定到当前方法中,【注:apply里面是 数组,这是它和 call方法的区别】
141+ } ( ) ; // 这里使用一个立即调用的函数表达式来确保this指向正确
142+ }
143+
144+ function Fn3 ( num1 , num2 ) {
145+ var boundSum = sum . bind ( this , num1 , num2 ) ; //bind方法创建一个新的函数,在调用时this值被绑定到传入的第一个参数上,后续参数作为预设参数传递给函数。
146+ return boundSum ( ) ; // 调用绑定后的函数
147+ }
148+
149+ console . log ( '\ncall的调用:' , Fn1 ( 10 , 20 ) ) ;
150+ console . log ( '\napply的调用:' , Fn2 ( 50 , 30 ) ) ;
151+ console . log ( '\nbind的调用:' , Fn3 ( 70 , 80 ) ) ;
152+ }
153+
154+ //call apply 扩充函数的作用域:下如实现重载功能!
155+ {
156+ window . color = 'red' ; //创建一个全局变量
157+ var obj = { color : 'blue' } //创建一个对象
158+
159+ function mupiao ( ) {
160+ alert ( this . color ) ; //mupiao函数在这里就只是把自己的color对应的值弹出来(使用call()、aplly()来扩充作用域的最大好处就是对象不需要与方法有任何耦合关系。)
161+ }
162+
163+ mupiao . call ( window ) ; //调用mupiao方法
164+ mupiao . call ( obj ) ;
165+ }
166+
167+
168+ //call apply 方法的【原理】简单模拟与实现
169+ {
170+ function test1 ( a , b ) { //函数或方法(实现求和功能)
171+ return a + b ;
172+ }
173+
174+ function Obj ( x , y ) { //自定义对象
175+ this . x = x ; //属性等于它自己
176+ this . y = y ;
177+ }
178+
179+ var o = new Obj ( 10 , 20 ) ; //实例化自定义对象
180+ o . method = test1 ; //用o对象的method方法来接收test1方法【此时: o.method到相当于test1了!】
181+ alert ( '结果:' + o . method ( o . x , o . y ) ) ;
182+ delete o . method ; //因为o.method是临时定义的,所以用完要删除掉!
183+
184+ //alert(test1.call(o , o.x , o.y));
185+ }
186+ </ script >
187+
188+ </ html >
0 commit comments