威尼斯人线上娱乐

JavaScript深远之call和apply的模拟落成,长远之call和apply的模拟完成

28 1月 , 2019  

JavaScript 深入之类数组对象与 arguments

2017/05/27 · JavaScript
· arguments

初稿出处: 冴羽   

JavaScript 长远之call和apply的模仿达成

2017/05/25 · JavaScript
· apply,
call

原稿出处: 冴羽   

因此call和apply的模仿完毕,带你揭开call和apply改变this的本色

JavaScript之父:Brendan Eich 。

-基本语法:借鉴了C语言和Java语言。
-数据结构:借鉴了Java,包涵将值分成原始值和目标两大类。

  • 函数的用法:借鉴了Scheme和Awk语言,将函数当成第一等老百姓,引入闭包。
  • 原型继承模型:借鉴了Self语言。
  • 正则表明式:借鉴了Perl语言。
  • 字符串和数组处理:借鉴了Python语言。

类数组对象

所谓的类数组对象:

不无一个 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
}

即使如此,为何叫做类数组对象啊?

那让大家从读写、获取长度、遍历五个地点看看那两个对象。

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 函数执行了

call
一句话介绍 call:
call() 方法在采纳一个指定的 this
值和几何个指定的参数值的前提下调用某个函数或措施。

JavaScript与ECMAScript的关系?
  • ECMAScript规定了浏览器脚本语言的专业。
  • ECMAScript是JavaScript的规格。

读写

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’;

模仿完成率先步

那么大家该怎么模拟落成那四个效益啊?

试想当调用 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 哎!是否很手舞足蹈!(~ ̄▽ ̄)~

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

怎么在浏览器中运作JavaScript?
  • <script> console.log(‘运行JS’) </script>
  • <script src=’./*’> </script>

长度

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

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

宪章达成第二步

最一初阶也讲了,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

(๑•̀ㅂ•́)و✧

小心两点:
call 改变了 this 的指向,指向到 foo
bar 函数执行了

JavaScript 讲明变量
  • var a;
  • let a;

遍历

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

故此究竟依然类数组呐……

一步一趋完结第三步

效仿代码已经达成 80%,还有多个小点要小心:

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

宪章达成率先步
那就是说大家该怎么模拟已毕那三个成效呢?
试想当调用 call 的时候,把 foo 对象改造成如下:
var foo = { value: 1, bar: function() { console.log(this.value)
}};foo.bar(); // 1

变量赋值
  • ES5

var a = 1;  //window.a = 1;  全局变量
function(){var a = 1;} //只能在函数体内访问到变量a
  • ES6新增结构赋值

let a = 1; //window.a ===undefined;
{
let a,b,c;
[a,b,c=3] = [1,2];   // let a = 1; let b = 2; let b =3;
}
{
let a,b,c;
[a,,b,,c] = [1,2,3,4,5,6,7,8,9,10];
console.log(a,b,c); //1,3,5
}
{
let o = {a:1,b:2};
let {a,b} = o;
console.log(a,b);//1,2
}
{
let o = {a:1,b:2};
let {a=2,b} = o;
console.log(a,b);//1,2
}
{
let metaData = {
 number:'1',
 info:[{
name:'chen'
}]
};
let {number:Num,info:[{name:name}]} = metaData;
console.log(Num,name);   // Num:'1',name:'chen'
}
{
    function test(){
         return [1,2,3,4,5,6,7]
     }
  let a;
[...a] = test(); // let a = [1,2,3,4,5,6,7];
}
{
let a = 1; let b = 2;
[a,b] = [b,a];
console.log(a,b)  //变量交换
}
{
let a,b,c;
[a,b,...c] = [1,2,3,4,5,6,7];  // let a = 1;let b = 2; let c = [4,5,6,7];
}
{
let a,b;
({a,b} ={a:1,b:2});
console.log(a,b); // 1,2;
}

调用数组方法

如果类数组就是随便的想用数组的艺术如何做呢?

既然不可能间接调用,我们得以用 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"]

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;
}

这几个时候 this 就对准了 foo,是否很简短吗?
唯独这么却给 foo 对象自我添加了一个性质,那可充足呀!
可是也不用担心,大家用 delete 再删除它不就好了~
就此我们模拟的步子可以分成:
将函数设为对象的属性
履行该函数
删除该函数

JavaScript 变量阐明进步
  • ES5

console.log(a); //undefind
var a = 1;
//等同如下
var a;
console.log(a);  //undefind
a = 1;
  • ES6:let注解变量不升官

console.log(a); // ReferenceError: a is not defined
let a = 1;

类数组转对象

在上头的例子中早就提到了一种类数组转数组的法子,再补充七个:

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()等)也回到类数组对象。

驷不及舌参考

微博问题 无法运用call、apply、bind,怎么样用 js 落成 call 或者 apply
的效应?

如上个例证为例,就是:
// 第一步foo.fn = bar// 第二步foo.fn()// 第三步delete foo.fn

标识符
  • 概念:识别具体对象的一个称谓(大小写敏感),如变量名,函数名。
  • 规则:
    • 先是个字符,然而任意Unicode字母,以及美元符号($),和下划线(_)。
    • 第二个字符以及背后的字符,除了Unicode,加元符号以及下划线,还足以是数字0-9。
  • 保留字和严重性字无法看做标识符(如:var 、class、false、true)。

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’)

打印结果如下:

威尼斯人线上娱乐 1

咱俩得以阅览除了类数组的索引属性和length属性之外,还有一个callee属性,接下去我们一个一个介绍。

深深体系

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深远之call和apply的模拟落成,长远之call和apply的模拟完成。JavaScript 深切之实践上下文
  8. JavaScript 深切之闭包
  9. JavaScript 深远之参数按值传递

    1 赞 收藏
    评论

威尼斯人线上娱乐 2

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

注释
  • 单行:/那是注释/。
  • 多行:/*那是注释*/。

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

凑巧可以打印 1 哎!是还是不是很心情舒畅!(~ ̄▽ ̄)~
模仿落成第二步
最一开始也讲了,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

区块(块级成效域)
  • ES5:不设有块级功用域

{
var a = 1;
}
console.log(a); // 1
  • ES6:使用let、const表明变量或常量(存在块级功用域)

{
let a = 1; const b =1;
}
console.log(a); // ReferenceError: a is not defined
console.log(b); // ReferenceError: a is not defined
{
let a = 1;
let a = 2;
console.log(a) //"SyntaxError: Identifier 'a' has already been declared(同一作用域重复声明一个变量报错)。
}
{
var a = 1;
var a = 2;
console.log(a);//2 var 重复声明同一变量取最后一次声明的赋值。
}

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 对象的几个注意要点:

留意:传入的参数并不确定,那可怎么做?
不急,大家可以从 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]

规格语句
  • if语句

if(true){
console.log('我被执行了')
}else{
console.log('我永远不会被执行')
}
  • switch语句

var f = 'apple';
if(f ==='banana'){
console.log('banana')
}else if(f==='apple'){
console.log('apple')
}
//多个if(){}else if{}嵌套时使用switch语句
switch(f){
case 'banana' : console.log('banana');
break;
case 'apple':console.log('apple');
break;
default: console.log('default');
}
  • 首祚运算符

    – expression ? do(true): do(false);

 let a = false;
 let b = a ? 1:2;
 console.log(b) // 2;
}```

- while循环语句
 - 

{
let i = 0;
while(i<10){
console.log(i); //0~9
i++;
}
}
{
let i = 11;
do{
console.log(i);
i–;
}while(i<10);
}

- for循环语句

for(let i=0;i<100;i++){
console.log(i);//0~99
}

- break和continue关键字

{
for(let i=0;i<10;i++){

if(i>=5){break;}   
 console.log(i); //0~4

}
}
{
for(let i=0; i<10;i++){
if(i<=5){continue;}
console.log(i);// 6~9
}
}

##### 数据类型
- 数值(number)
- 字符串(string)
- 布尔值(boolean) 
 - 5个假值(null,undefined,0,'',NaN)
- undefined
- null
- 对象(object)
  - 数组(Array)  是一种对象
  - 函数(Function) 是一种对象
  - 普通对象  

##### 类型转换

{
let number = 1;
let string = number+”;
console.log(typeof string,string) //string,”1″
}
{
let number = 1;
let bool =!number;
console.log(typeof bool,bool) //boolean,false
}
{
let string = ‘123’;
//let number = string -0;
let number = +string;
console.log(typeof number,number) //number,123
}
{
let string = ‘hello’;
let number = string – 0;
console.log(typeof number,number) //NaN;
}
{
let bool = true;
let number = bool -0;
//let number = !bool -0; number, 0
console.log(typeof number,number) //number,1
}

- ##### 字符串方法以及遍历
  - ES5

//遍历
{
let string = “hello”;
for(let i = 0;i<string.length;i++){

console.log(string[i])

}
}
//method
{
let str = ‘hello’;
let newStr = str.substring(1,2); // [start,end)
console.log(str); // ‘hello’
console.log(newStr) // ‘e’
}
{
let str = ‘world’;
let newStr = str.substr(1,2); //start, deleteCount
console.log(str); // ‘world’
console.log(newStr) // ‘or’
}

- ES6

{
let string = “world”;
for(let i of string){
console.log(i)
}
}

 ##### 声明对象以及读写属性、遍历对象
- Obejct是一种无序的集合
 - ES5

{
let o = {
name:’小花’,
age:18,
skill: function(){console.log(‘say’)}
};
/*let o = new Object({
name:’小花’
}) */
console.log(o.name); //”小花”
o.name = ‘小草’;
console.log(o[‘name’]);//”小草”
console.log(‘name’ in o); //true
delete o.name; //o = {};
}
{
let o = {
name:’小草’,
age:18
}
for(let i in o){
console.log(i); //name,age
console.log(o[i]); //小草,18
}
}

 - ES6

{
let name = ‘xiaohua’,age = 16;
let o = {
name,
age,
skill(){
console.log(‘say’)
}
}
console.log(o.skill())
}
{
let a = ‘b’;
let es5_obj = {
a:’c’,
b:’c’
}
let es6_obj ={
[a]:’c’ //key可以用变量
}
console.log(es5_obj,es6_obj);
}

##### 声明数组、遍历数组
- Array是一种有序的集合

- 数组的一些方法
  - ES5

{
let array = [1,2,3,[4,5,6],{5:”6″,6:”7″,7:”8″}]; //表明数组
console.log(array);
console.log(array.length);//5;
for(let i = 0; i<array.length;i++){
console.log(i,”-“,array[i]);
}
array.push(9,10,11,[12,13,14],{name:”array”});
console.log(array);
array.pop();
console.log(array.length);
}
{
let arr = [2,3,1,4,5];
arr.sort();
console.log(arr);//[1,2,3,4,5]
arr.sort(function(a,b){return a<b});
console.log(arr);//[5,4,3,2,1]
}
{
let arr = [1,2,3,4,5];
let deleteArr = arr.splice(0,2,0,1,2);//array.splice(start, deleteCount,
item1, item2, …)
console.log(arr);
console.log(deleteArr);
}
{
let arr = [1,2,3,4];
let arrStr = arr.join(‘–‘);
console.log(arr);
console.log(arrStr);
let newArrStr = arrStr.split(‘–‘);
console.log(newArrStr);
}

  - ES6

{ //将伪数组转换成数组
function arg(){
argArray = Array.from(arguments,(item)=> item2);
//Array.from(arrayLike[, mapFn[, thisArg]])
console.log(argArray)
}
/

argArray = Array.from(arguments);
argArray.forEach(function(item){console.log(item)})
*/
arg(1,2,3,4,5)
}
{ //填充数组
let array = [1,2,3,4,5]; //arr.fill(value) arr.fill(value, start)
arr.fill(value, start, end)
newArray = array.fill(0);
console.log(newArray);
console.log(array);
console.log(array.fill(9,0,3));
console.log(array);
}
{ //遍历数组
let array = [1,2,3,4,5];
for(let i of array){
console.log(i) //1,2,3,4,5
}
for(let i of array.keys()){
console.log(i)//0,1,2,3,4
}
for(let [i,v] of array.entries()){
console.log(i,v)
}
console.log(array.find((item)=>item>3));
//查找满意条件,只回去第三个
console.log(array.findIndex(item=>item>3));
{
let array = [1,2,3,4,5];
console.log(array.includes(1,0))//arr.includes(searchElement, fromIndex)
//是不是包罗
}
}

##### 声明函数,函数提升,arguments及...rest,length属性,闭包,同步V.S.异步
 - ES5

// var say = function(){}; 只会进步var say
function say(x){ //进步整个函数
console.log(x);
console.log(arguments)
//将传入所有实参生成一个伪数组,其实是一个key为平稳下标的靶子
return x //使函数具有重返值
}
say(‘hello’); //传入实参
console.log(say.length);//行参个数
var c =say(‘hello’); //重返值赋予变量c
console.log(c);
{ //立时执行函数 避免全局污染
!function(){
var a = 1;
console.log(a)
}();
!function(){
var a = 2;
console.log(a)
}();
}
{ //闭包
function f1(){
var a = 1;
function f2(){
a++;
console.log(a)
}
return f2;
}

let result = f1();
result();
}
{//同步
console.log(1);
console.log(2);
console.log(3);
}
{//异步
console.log(1);
setTimeout(function(){
console.log(2);
},3000)
console.log(3);
}

 - ES6

{ //ES6留存块及效能域,不必要选取匿名函数来防备全局污染
let a =1 ;
console.log(a);
}
{
let a = 2;
console.log(a);
}
{
function say(x,y = ‘world’){ //行参默许值
console.log(x,y);
}
say(‘hello’);
}
{
let say = (…arg)=>{
console.log(arg);
for(let i of arg){
console.log(i);
}
console.log(typeof arg.push) //那是一个真数组,和arguments分歧
}
say(‘hello’,’world’);
}
{
let x = ‘china’;
let say = (x,y = x)=>{
console.log(x,y);
}
say(‘hello’);//”hello hello”
}
{
let x = ‘china’;
let say = (z,y = x)=>{ //变量作用域,和上一个例子相比较
console.log(z,y);
}
say(‘hello’);//”hello china”
}
{
let say = (x)=> x ;//此处倘诺加{}就不会有重返值
/*
var say = function(x){
return x
}
*/
let result = say(100);
console.log(result)
}
{ //函数作为再次回到值,函数作为参数的例子
let qux= ()=> (callback)=> callback();
let result = qux();
console.log(result);
result(()=>{console.log(“执行了”)})
}

类、原型、继承(面向对象)
  - ES5

{
function Person(name,age,gender){
this.name = name;
this.age =age;
this.gender = gender;
}
Person.prototype.born = function(){
console.log(‘born’)
}
function Man(){
Person.apply(this,arguments)
this.sex = ‘male’
}
let empty = function(){};
empty.prototype = Person.prototype;
Man.prototype = new empty();
console.log(Man.prototype.constructor = Man);
var man1 = new Man(‘张三’,18,’male’);
console.log(man1)
}
{
var name,age,gender;
var Person = {
name:name,
age:age,
gender:gender,
born:function(){console.log(‘born’)}
}
var Man = Object.create(Person);
Man.sex = ‘male’;
console.log(Man)
}

  - ES6 

{//ES6 类
class Person{
constructor(name=’张三’,age= 18,gender=’male’){
this.name = name;
this.age =age;
this.gender = gender;
};
born(){
console.log(‘born’)
};
die(){
console.log(‘die’)
}
}
console.log(new Person)
class Man extends Person{//类的持续
constructor(){
super();
this.sex = ‘Man’
}
}
let man1 = new Man()
console.log(man1)
console.log(man1.born())
}

##### 标准库
 - Array
 - String
 - Number
 - Function
 - Boolean
 - Math(console.dir(Math)  )
  - Math.PI;              //3.141592653589793
  - Math.SQRT2;      //1.4142135623730951
  -Math.pow();
  -Math.sqrt(); 
  - Math.random()*50+50 ;// 50~100之间的伪随机数
 - Date
  - new Date() 
    - 
       ```
{
let date = new Date();
  console.log(date);//Sat Jun 03 2017 01:27:41 GMT+0800 (CST)
  console.log(date.getFullYear())  //2017
  console.log(date.getMonth()) // 5   0~11个月
  console.log(date.getDate())  //3    
  console.log(date.getDay())  //6 星期日为0,星期一为1。
  console.log(date.getHours());
  console.log(date.getMinutes())
  console.log(date.getSeconds())
}
  • toLocaleString()

  • Promise

{
  function breakfast(callback){
     console.log('吃早饭');
     callback&&callback();
  }
  function lunch(){
     console.log('吃午饭');
  }
  console.log(breakfast(lunch))
}
{
  let breakfast = function(){
    console.log('吃早饭');
    return new Promise(function(resolve,reject){
      resolve();
    })
  } 
  let lunch = function(){
    console.log('吃午饭');
    return new Promise(function(resolve,reject){
     resolve();
    })
  }
  let dinner = function(){
    console.log('吃晚饭')
  }
 breakfast().then(lunch).then(dinner)
}

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
是不会共享的。

不定长的参数问题化解了,我们随后要把那些参数数组放到要执行的函数的参数里面去。
//
将数组里的要素作为三个参数放进函数的形参里context.fn(args.join(‘,’))//
(O_o)??// 这么些艺术肯定是十分的啦!!!

传送参数

将参数从一个函数传递到另一个函数

// 使用 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)

恐怕有人想到用 ES6 的法子,但是 call 是 ES3 的办法,大家为了模仿完成一个
ES3 的点子,要用到ES6的点子,好像……,嗯,也得以啊。可是大家本次用 eval
方法拼成一个函数,类似于那般:
eval(‘context.fn(‘ + args +’)’)

强大的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);

那里 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

应用

arguments的行使其实过多,在下个连串,也就是 JavaScript
专题种类中,大家会在 jQuery 的 extend 完毕、函数柯里化、递归等情景看见
arguments 的人影。这篇小说就不具体举行了。

假如要总括那一个现象的话,暂时能体悟的不外乎:

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

迎接留言回复。

(๑•̀ㅂ•́)و✧
萧规曹随完成第三步
效仿代码已经已毕 80%,还有七个小点要留心:
1.this 参数可以传 null,当为 null 的时候,视为指向 window
举个例子:
var value = 1;function bar() { console.log(this.value);}bar.call(null);
// 1

深刻种类

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 收藏
    评论

威尼斯人线上娱乐 3

就算那几个事例本身不选拔 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// }

不过都很好解决,让大家一贯看第三版也就是最终一版的代码:
// 第三版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); // 2console.log(bar.call2(obj,
‘kevin’, 18));// 1// Object {// value: 1,// name: ‘kevin’,// age: 18// }

到此,大家达成了 call 的模拟完毕,给协调一个赞 b( ̄▽ ̄)d
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;}

深入序列
JavaScript深远体系目录地址:https://github.com/mqyqingfeng/Blog。
JavaScript长远系列猜度写十五篇左右,意在帮大家捋顺JavaScript底层知识,重点教学如原型、作用域、执行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、继承等困难概念。
比方有荒唐或者不审慎的地点,请务必给予指正,至极谢谢。即使喜欢仍旧持有启发,欢迎star,对作者也是一种鞭策。


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图