大奖888官网登录举个例子,举个例子

2019-11-06 15:56栏目:前端开发
TAG:

callee属性

Arguments 对象的 callee 属性,通过它可以调用函数本人。

讲个闭包精粹面试题使用 callee 的解除方法:

var data = []; for (var i = 0; i 3; i++) { (data[i] = function () { console.log(arguments.callee.i) }).i = i; } data[0](); data[1](); data[2](); // 0 // 1 // 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var data = [];
 
for (var i = 0; i  3; i++) {
    (data[i] = function () {
       console.log(arguments.callee.i)
    }).i = i;
}
 
data[0]();
data[1]();
data[2]();
 
// 0
// 1
// 2

接下去讲讲 arguments 对象的多少个注意要点:

call

一句话介绍 call:

call() 方法在行使一个钦点的 this 值和若干个钦命的参数值的前提下调用有个别函数或艺术。

举个例证:

var foo = { value: 1 }; function bar() { console.log(this.value); } bar.call(foo); // 1

1
2
3
4
5
6
7
8
9
var foo = {
    value: 1
};
 
function bar() {
    console.log(this.value);
}
 
bar.call(foo); // 1

在乎两点:

  1. call 改变了 this 的指向,指向到 foo
  2. bar 函数试行了

读写

console.log(array[0]); // name console.log(arrayLike[0]); // name array[0] = 'new name'; arrayLike[0] = 'new name';

1
2
3
4
5
console.log(array[0]); // name
console.log(arrayLike[0]); // name
 
array[0] = 'new name';
arrayLike[0] = 'new name';

模仿完毕第三步

宪章代码已经变成 百分之七十,还恐怕有八个小点要小心:

1.this 参数能够传 null,当为 null 的时候,视为指向 window

比如:

var value = 1; function bar() { console.log(this.value); } bar.call(null); // 1

1
2
3
4
5
6
7
var value = 1;
 
function bar() {
    console.log(this.value);
}
 
bar.call(null); // 1

就算这几个事例自身不应用 call,结果依然故笔者同样。

2.函数是能够有再次回到值的!

比如:

var obj = { value: 1 } function bar(name, age) { return { value: this.value, name: name, age: age } } console.log(bar.call(obj, 'kevin', 18)); // Object { // value: 1, // name: 'kevin', // age: 18 // }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var obj = {
    value: 1
}
 
function bar(name, age) {
    return {
        value: this.value,
        name: name,
        age: age
    }
}
 
console.log(bar.call(obj, 'kevin', 18));
// Object {
//    value: 1,
//    name: 'kevin',
//    age: 18
// }

然则都很好消除,让我们平素看第三版约等于最终风姿罗曼蒂克版的代码:

// 第三版 Function.prototype.call2 = function (context) { var context = context || window; context.fn = this; var args = []; for(var i = 1, len = arguments.length; i len; i++) { args.push('arguments[' + i + ']'); } var result = eval('context.fn(' + args +')'); delete context.fn return result; } // 测量试验一下 var value = 2; var obj = { value: 1 } function bar(name, age) { console.log(this.value); return { value: this.value, name: name, age: age } } bar.call(null); // 2 console.log(bar.call2(obj, 'kevin', 18)); // 1 // Object { // value: 1, // name: 'kevin', // age: 18 // }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 第三版
Function.prototype.call2 = function (context) {
    var context = context || window;
    context.fn = this;
 
    var args = [];
    for(var i = 1, len = arguments.length; i  len; i++) {
        args.push('arguments[' + i + ']');
    }
 
    var result = eval('context.fn(' + args +')');
 
    delete context.fn
    return result;
}
 
// 测试一下
var value = 2;
 
var obj = {
    value: 1
}
 
function bar(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}
 
bar.call(null); // 2
 
console.log(bar.call2(obj, 'kevin', 18));
// 1
// Object {
//    value: 1,
//    name: 'kevin',
//    age: 18
// }

到此,大家做到了 call 的效仿达成,给自身三个赞 b( ̄▽ ̄卡塔尔d

深深连串

JavaScript深刻系列目录地址:。

JavaScript深远种类猜度写十三篇左右,目的在于帮大家捋顺JavaScript底层知识,入眼教学如原型、功用域、试行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、世袭等难处概念。

假使有怪诞或许非常大心的地点,请必得赋予指正,十分多谢。假设喜欢只怕持有启示,款待star,对小编也是生龙活虎种驱策。

  1. JavaScirpt 深切之从原型到原型链
  2. JavaScript 深刻之词法作用域和动态功用域
  3. JavaScript 深入之施行上下文栈
  4. JavaScript 浓重之变量对象
  5. JavaScript 浓重之作用域链
  6. JavaScript 深入之从 ECMAScript 标准解读 this
  7. JavaScript 深切之实行上下文
  8. JavaScript 深刻之闭包
  9. JavaScript 深刻之参数按值传递
  10. JavaScript 深刻之call和apply的模拟达成
  11. JavaScript 深切之bind的模仿达成
  12. JavaScript 深入之new的依样画葫芦实现

    1 赞 2 收藏 评论

大奖888官网登录 1

apply的效仿完成

apply 的落到实处跟 call 相近,在此边直接给代码,代码来自于乐乎 @郑航的兑现:

Function.prototype.apply = function (context, arr) { var context = Object(context) || window; context.fn = this; var result; if (!arr) { result = context.fn(); } else { var args = []; for (var i = 0, len = arr.length; i len; i++) { args.push('arr[' + i + ']'); } result = eval('context.fn(' + args + ')') } delete context.fn return result; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Function.prototype.apply = function (context, arr) {
    var context = Object(context) || window;
    context.fn = this;
 
    var result;
    if (!arr) {
        result = context.fn();
    }
    else {
        var args = [];
        for (var i = 0, len = arr.length; i  len; i++) {
            args.push('arr[' + i + ']');
        }
        result = eval('context.fn(' + args + ')')
    }
 
    delete context.fn
    return result;
}

类数组转对象

在地方的例证中早就涉嫌了大器晚成连串数组转数组的法子,再补偿多个:

var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 } // 1. slice Array.prototype.slice.call(arrayLike); // ["name", "age", "sex"] // 2. splice Array.prototype.splice.call(arrayLike, 0); // ["name", "age", "sex"] // 3. ES6 Array.from Array.from(arrayLike); // ["name", "age", "sex"] // 4. apply Array.prototype.concat.apply([], arrayLike)

1
2
3
4
5
6
7
8
9
var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
// 1. slice
Array.prototype.slice.call(arrayLike); // ["name", "age", "sex"]
// 2. splice
Array.prototype.splice.call(arrayLike, 0); // ["name", "age", "sex"]
// 3. ES6 Array.from
Array.from(arrayLike); // ["name", "age", "sex"]
// 4. apply
Array.prototype.concat.apply([], arrayLike)

那么为何会讲到类数组对象啊?以至类数组有哪些应用吗?

要说起类数组对象,Arguments 对象正是三个类数组对象。在客商端 JavaScript 中,一些 DOM 方法(document.getElementsByTagName()等)也回到类数组对象。

深入系列

JavaScript浓重连串目录地址:。

JavaScript深切种类推测写十九篇左右,意在帮我们捋顺JavaScript底层知识,重点讲授如原型、成效域、实施上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、世袭等困难概念。

如果有不当也许不严谨的地点,请必需付与指正,非常多谢。假诺喜欢或然持有启迪,应接star,对小编也是后生可畏种驱策。

本系列:

  1. JavaScirpt 深切之从原型到原型链
  2. JavaScript 浓郁之词法效率域和动态效用域
  3. JavaScript 深切之实行上下文栈
  4. JavaScript 浓郁之变量对象
  5. JavaScript 深刻之效果域链
  6. JavaScript 深刻之从 ECMAScript 标准解读 this
  7. JavaScript 深远之实行上下文
  8. JavaScript 浓重之闭包
  9. JavaScript 深切之参数按值传递

    1 赞 收藏 评论

大奖888官网登录 2

遍历

for(var i = 0, len = array.length; i len; i++) { …… } for(var i = 0, len = arrayLike.length; i len; i++) { …… }

1
2
3
4
5
6
for(var i = 0, len = array.length; i  len; i++) {
   ……
}
for(var i = 0, len = arrayLike.length; i  len; i++) {
    ……
}

是或不是很像?

那类数组对象能够利用数组的秘籍吗?比方:

arrayLike.push('4');

1
arrayLike.push('4');

不过上述代码会报错: arrayLike.push is not a function

就此究竟照旧类数组呐……

依傍完成率先步

那么大家该怎么模拟完毕那八个作用啊?

试想当调用 call 的时候,把 foo 对象更改成如下:

var foo = { value: 1, bar: function() { console.log(this.value) } }; foo.bar(); // 1

1
2
3
4
5
6
7
8
var foo = {
    value: 1,
    bar: function() {
        console.log(this.value)
    }
};
 
foo.bar(); // 1

本条时候 this 就对准了 foo,是或不是一点也不细略吗?

唯独如此却给 foo 对象自小编加多了壹特性质,那可极其啊!

然而也不用忧虑,我们用 delete 再删除它不就好了~

所以我们模拟的手续能够分为:

  1. 将函数设为对象的属性
  2. 进行该函数
  3. 去除该函数

以上个例证为例,便是:

// 第一步 foo.fn = bar // 第二步 foo.fn() // 第三步 delete foo.fn

1
2
3
4
5
6
// 第一步
foo.fn = bar
// 第二步
foo.fn()
// 第三步
delete foo.fn

fn 是目的的属性名,反正最终也要刨除它,所以起成什么都不留意。

基于那个思路,我们得以尝尝着去写第大器晚成版的 call2 函数:

// 第生机勃勃版 Function.prototype.call2 = function(context) { // 首先要拿走调用call的函数,用this能够收获 context.fn = this; context.fn(); delete context.fn; } // 测量检验一下 var foo = { value: 1 }; function bar() { console.log(this.value); } bar.call2(foo); // 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 第一版
Function.prototype.call2 = function(context) {
    // 首先要获取调用call的函数,用this可以获取
    context.fn = this;
    context.fn();
    delete context.fn;
}
 
// 测试一下
var foo = {
    value: 1
};
 
function bar() {
    console.log(this.value);
}
 
bar.call2(foo); // 1

正要能够打字与印刷 1 哎!是或不是很欢腾!(~ ̄▽ ̄)~

类数组对象

所谓的类数组对象:

具备二个 length 属性和若干索引属性的靶子

举例:

var array = ['name', 'age', 'sex']; var arrayLike = { 0: 'name', 1: 'age', 2: 'sex', length: 3 }

1
2
3
4
5
6
7
8
var array = ['name', 'age', 'sex'];
 
var arrayLike = {
    0: 'name',
    1: 'age',
    2: 'sex',
    length: 3
}

即便如此,为啥叫做类数组对象啊?

那让大家从读写、获取长度、遍历七个地点看看那五个指标。

JavaScript 深刻之call和apply的效仿达成

2017/05/25 · JavaScript · apply, call

原稿出处: 冴羽   

强大的ES6

行使ES6的 … 运算符,大家得以轻易转成数组。

function func(...arguments) { console.log(arguments); // [1, 2, 3] } func(1, 2, 3);

1
2
3
4
5
function func(...arguments) {
    console.log(arguments); // [1, 2, 3]
}
 
func(1, 2, 3);

关键参照

网易难点 不可能运用call、apply、bind,怎样用 js 落成 call 只怕 apply 的职能?

arguments 和相应参数的绑定

function foo(name, age, sex, hobbit) { console.log(name, arguments[0]); // name name // 改动形参 name = 'new name'; console.log(name, arguments[0]); // new name new name // 改变arguments arguments[1] = 'new age'; console.log(age, arguments[1]); // new age new age // 测验未传入的是还是不是会绑定 console.log(sex); // undefined sex = 'new sex'; console.log(sex, arguments[2]); // new sex undefined arguments[3] = 'new hobbit'; console.log(hobbit, arguments[3]); // undefined new hobbit } foo('name', 'age')

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function foo(name, age, sex, hobbit) {
 
    console.log(name, arguments[0]); // name name
 
    // 改变形参
    name = 'new name';
 
    console.log(name, arguments[0]); // new name new name
 
    // 改变arguments
    arguments[1] = 'new age';
 
    console.log(age, arguments[1]); // new age new age
 
    // 测试未传入的是否会绑定
    console.log(sex); // undefined
 
    sex = 'new sex';
 
    console.log(sex, arguments[2]); // new sex undefined
 
    arguments[3] = 'new hobbit';
 
    console.log(hobbit, arguments[3]); // undefined new hobbit
 
}
 
foo('name', 'age')

流传的参数,实参和 arguments 的值会共享,当未有传届期,实参预 arguments 值不会分享

除开,以上是在非严酷方式下,假设是在从严方式下,实参和 arguments 是不会分享的。

模仿完毕第二步

最大器晚成开端也讲了,call 函数还是能够给定参数履行函数。举例:

var foo = { value: 1 }; function bar(name, age) { console.log(name) console.log(age) console.log(this.value); } bar.call(foo, 'kevin', 18); // kevin // 18 // 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var foo = {
    value: 1
};
 
function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}
 
bar.call(foo, 'kevin', 18);
// kevin
// 18
// 1

在乎:传入的参数并不确定,那可怎么做?

不急,大家得以从 Arguments 对象中取值,抽出第四个到最后一个参数,然后嵌入叁个数组里。

诸如那样:

// 以上个例证为例,那个时候的arguments为: // arguments = { // 0: foo, // 1: 'kevin', // 2: 18, // length: 3 // } // 因为arguments是类数组对象,所以可以用for循环 var args = []; for(var i = 1, len = arguments.length; i len; i++) { args.push('arguments[' + i + ']'); } // 执行后 args为 [foo, 'kevin', 18]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 以上个例子为例,此时的arguments为:
// arguments = {
//      0: foo,
//      1: 'kevin',
//      2: 18,
//      length: 3
// }
// 因为arguments是类数组对象,所以可以用for循环
var args = [];
for(var i = 1, len = arguments.length; i  len; i++) {
    args.push('arguments[' + i + ']');
}
 
// 执行后 args为 [foo, 'kevin', 18]

不定长的参数难题消除了,我们随后要把这么些参数数组放到要实施的函数的参数里面去。

// 将数组里的成分作为多个参数放进函数的形参里 context.fn(args.join(',')) // (O_o)?? // 那个艺术自然是特别的啦!!!

1
2
3
4
// 将数组里的元素作为多个参数放进函数的形参里
context.fn(args.join(','))
// (O_o)??
// 这个方法肯定是不行的啦!!!

想必有人想到用 ES6 的法门,不过 call 是 ES3 的章程,大家为了参考完结一个ES3 的措施,要用到ES6的艺术,好像……,嗯,也得以啊。不过我们这一次用 eval 方法拼成二个函数,相通于那般:

eval('context.fn(' + args +')')

1
eval('context.fn(' + args +')')

这里 args 会自动调用 Array.toString() 那个艺术。

于是大家的第二版克服了五个大难点,代码如下:

// 第二版 Function.prototype.call2 = function(context) { context.fn = this; var args = []; for(var i = 1, len = arguments.length; i len; i++) { args.push('arguments[' + i + ']'); } eval('context.fn(' + args +')'); delete context.fn; } // 测量检验一下 var foo = { value: 1 }; function bar(name, age) { console.log(name) console.log(age) console.log(this.value); } bar.call2(foo, 'kevin', 18); // kevin // 18 // 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 第二版
Function.prototype.call2 = function(context) {
    context.fn = this;
    var args = [];
    for(var i = 1, len = arguments.length; i  len; i++) {
        args.push('arguments[' + i + ']');
    }
    eval('context.fn(' + args +')');
    delete context.fn;
}
 
// 测试一下
var foo = {
    value: 1
};
 
function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}
 
bar.call2(foo, 'kevin', 18);
// kevin
// 18
// 1

(๑•̀ㅂ•́)و✧

传送参数

将参数从二个函数字传送递到另二个函数

// 使用 apply 将 foo 的参数字传送递给 bar function foo() { bar.apply(this, arguments); } function bar(a, b, c) { console.log(a, b, c); } foo(1, 2, 3)

1
2
3
4
5
6
7
8
9
// 使用 apply 将 foo 的参数传递给 bar
function foo() {
    bar.apply(this, arguments);
}
function bar(a, b, c) {
   console.log(a, b, c);
}
 
foo(1, 2, 3)

Arguments对象

接下去珍贵讲讲 Arguments 对象。

Arguments 对象只定义在函数体中,包涵了函数的参数和任何属性。在函数体中,arguments 指代该函数的 Arguments 对象。

举个例子:

function foo(name, age, sex) { console.log(arguments); } foo('name', 'age', 'sex')

1
2
3
4
5
function foo(name, age, sex) {
    console.log(arguments);
}
 
foo('name', 'age', 'sex')

打字与印刷结果如下:

大奖888官网登录 3

大家得以看见除了类数组的索引属性和length属性之外,还或然有多个callee属性,接下去大家贰个二个介绍。

长度

console.log(array.length); // 3 console.log(arrayLike.length); // 3

1
2
console.log(array.length); // 3
console.log(arrayLike.length); // 3

JavaScript 深切之类数组对象与 arguments

2017/05/27 · JavaScript · arguments

初藳出处: 冴羽   

调用数组方法

设若类数组正是轻巧的想用数组的主意如何做吧?

既是无法直接调用,大家能够用 Function.call 直接调用:

var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 } Array.prototype.join.call(arrayLike, '&'); // name&age&sex Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"] // slice可以完毕类数组转数组 Array.prototype.map.call(arrayLike, function(item){ return item.toUpperCase(); }); // ["NAME", "AGE", "SEX"]

1
2
3
4
5
6
7
8
9
10
11
var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
 
Array.prototype.join.call(arrayLike, '&'); // name&age&sex
 
Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"]
// slice可以做到类数组转数组
 
Array.prototype.map.call(arrayLike, function(item){
    return item.toUpperCase();
});
// ["NAME", "AGE", "SEX"]

应用

arguments的应用其实过多,在下个星罗棋布,也即是 JavaScript 专项论题类别中,大家会在 jQuery 的 extend 完成、函数柯里化、递归等气象见到arguments 的人影。那篇作品就不具体进展了。

假定要总括这个景况的话,一时能想到的席卷:

  1. 参数不定长
  2. 函数柯里化
  3. 递归调用
  4. 函数重载

迎接留言回复。

length属性

Arguments对象的length属性,表示实参的长短,举例:

function foo(b, c, d){ console.log("实参的尺寸为:" + arguments.length) } console.log("形参的长短为:" + foo.length) foo(1) // 形参的长度为:3 // 实参的长度为:1

1
2
3
4
5
6
7
8
9
10
function foo(b, c, d){
    console.log("实参的长度为:" + arguments.length)
}
 
console.log("形参的长度为:" + foo.length)
 
foo(1)
 
// 形参的长度为:3
// 实参的长度为:1

版权声明:本文由大奖888-www.88pt88.com-大奖888官网登录发布于前端开发,转载请注明出处:大奖888官网登录举个例子,举个例子