本文中call和apply仅占小部分,主要还是关于自己在学习过程中踩到的坑的记录.
使用call方法将变量产生的数组进行转换
1 | function foo(a, b, c) { |
以上使用了两种方法,arr1使用了数组的reverse方法,并将数组的reverse方法借用给arguments,也就是说arguments使用了数组中的方法,之前的arguments是没有这个方法的。其最终产生的效果是,arr1还是数组的集合。
第二种方法其实是首先将数组的slice方法的作用域赋予给arguments,那么arguments其实是使用了slice的方法进行了数组的序列化,最终产生的效果其实是arr2最终变成了一个数组,然后使用数组,也就是arr2的作用域链中的reverse方法进行了调换。
arrow函数
箭头函数其实是对于单调乏味且冗长的function关键词的简写,如:
1 | var foo = a => { |
其实在这个情况下,以上的程序是等价于以下的程序的:
1 | var foo = function(a) { |
那么问题来了,这个箭头函数到底表示的是函数表达式还是函数声明呢?,经过一个简单的测试,发现其实这个箭头函数就是一个简单的函数表达式,我们来测试以下它的函数提升过程:
1 | foo(2); |
严格模式下必报的this指向问题
严格模式下,全局对象无法绑定到未进行修饰的函数声明,因此在全局作用域下,在函数内调用this时会造成报错: Cannot read property ‘a’ of undefined;1
2
3
4
5(function foo() {
"use strict";
var a = 2;
console.log(this.a); //Cannot read property 'a' of undefined;
})()
关于this的作用层级问题
对象中只有引用链的最顶层或者说是作用者的最后一层会影响其调用位置,来看一下下面的这个代码,很奇怪的事情是this居然指向的是obj1 而不是obj2,原因就是因为作用者的最后一层就是obj1.1
2
3
4
5
6
7
8
9
10
11
12function foo() {
console.log(this.a);
}
var obj1 = {
a: 1,
foo: foo
}
var obj2 = {
a: 2,
obj1: obj1
}
obj2.obj1.foo(); //输出的是1,也就是代表this其实指向的是obj1
引用类型常量的赋值问题
当函数内部制定了变量值后,输出的值是不一样的,我们来看一下例子:
function foo(x) {
x.push(4);
console.log(x); //输出的是[1,2,3,4],没毛病
x = [4,5,6];
x.push(7);
console.log(x); //输出[4,5,6,7]这个没毛病
}
var a = [1,2,3];
foo(a);
console.log(a); //这个情况下,a的值其实是[1,2,3,4];1
2
3
4
5其实主要的原因是这样的,当我们的a作为参数传到foo函数中的时候,foo中的参数x其实是获得了一个到a数组的指针,当x进行相应的数值处理操作的时候,会直接作用到a上面,但是当x的指针改变了,也就是x被重新赋值的时候,x的指针就指向新的[4,5,6]数组了,这个时候其实后面的push(7)的操作已经是对于新的数组,并没有对a数组进行相应的操作,故最后返回的a的值只是[1,2,3,4]
# 引用类型常量的赋值问题再探讨
一个很小的问题(其实涉及到的知识点和第五条是类似的),当我为一个变量赋予了一个常量值,但通过函数对这个常量值进行更改,那么更改会不会体现到这个常量值中呢?
function foo(x) {
x = x + 1;
console.log(x);
}
var a = 2;
foo(a);
console.log(a); //此时a还是为2`