JavaScript 函数参数、作用域及apply,this关键字

作用域
全局作用域:
不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象**window,**全局作用域的变量实际上被绑定到window的一个属性。

任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报ReferenceError错误。
'use strict';
var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // 'Learn JavaScript'

//以变量方式var foo = function () {}定义的函数实际上也是一个全局变量,因此,顶层函数的定义也被视为一个全局变量,并绑定到window对象:

function foo() {
    alert('foo');
}
foo(); // 直接调用foo()
window.foo(); // 通过window.foo()调用
  • 函数作用域: 无块级作用域,在for循环等语句块中是无法定义具有局部作用域的变量

    ES6引入了新的关键字let,用let替代var可以申明一个块级作用域的变量:

function foo() {
    var sum = 0;
    for (let i=0; i<100; i++) {
        sum += i;
    }
    i += 1; // SyntaxError
}
名字空间:把自己的所有变量和函数全部绑定到一个全局变量中 var jQuery={},采用 jQuery.func() 进行引用。
函数中的this关键字(在对象中绑定的函数,成为这个对象的方法)

坑一:在对象外部定义函数,在内部把该函数赋值给函数,直接调用函数,this找不到对象,以对象的方法调用,this为当前对象。

//作为函数(非绑定对象),内部this指向全局对象 window
function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};

xiaoming.age(); // 25, 正常结果
getAge(); // NaN

坑二:先拿到对象的函数,再进行调用也会报错

//要保证this指向正确,必须用obj.xxx()的形式调用!
var fn = xiaoming.age; // 先拿到xiaoming的age函数
fn(); // NaN

坑三:在函数内部定义的函数,并不能和对象绑定,this又指向undefined

RE:常用解决方法 — var that = this; 在方法内部捕获对象,之后再使用.

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var that = this; // 在方法内部一开始就捕获this
        function getAgeFromBirth() {
            var y = new Date().getFullYear();
            return y - that.birth; // 用that而不是this
        }
        return getAgeFromBirth();
    }
};

xiaoming.age(); // 25
//就可以放心地在方法内部定义其他函数,而不是把所有语句都堆到一个方法中。
用 apply 关键字绑定函数的 this 指向对象,并传递包装成 array的参数数组

(1) 装饰器: 动态改变原函数的行为

var count = 0;
var oldParseInt = parseInt; // 保存原函数

window.parseInt = function () {
    count += 1;
    return oldParseInt.apply(null, arguments); // 调用原函数(传递原参数)
};
// 测试:
parseInt('10');
parseInt('20');
parseInt('30');
count; // 3

(2) 绑定函数对象

getAge.apply(xiaoming,[]) 
//第一个参数为需要绑定的this变量,第二个参数为函数本身的参数数组Array.
  • 用 call 关键字绑定对象,并且把参数按顺序传入,与 apply 类似。
Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5
//对普通函数调用,我们通常把this绑定为null。
参数:arguments:

它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array

//如果abs(x)函数的参数x未定义将收到undefined,计算结果为NaN。
//要避免收到undefined,可以对参数进行检查:
function abs(x) {
    if (typeof x !== 'number') {
        throw 'Not a number';
    }
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}
参数:rest: ES6标准引入,将剩余参数组成新数组
'use strict';
function sum(...rest) {
   var sum = 0
   for(i=0;i<rest.length;i++)
      {
         sum +=rest[i]
}
   return sum;
}
//用来当做可变参数函数的输入参数
var i, args = [];
for (i=1; i<=100; i++) {
    args.push(i);
}
if (sum() !== 0) {
    alert('测试失败: sum() = ' + sum());
} else if (sum(1) !== 1) {
    alert('测试失败: sum(1) = ' + sum(1));
} else if (sum(2, 3) !== 5) {
    alert('测试失败: sum(2, 3) = ' + sum(2, 3));
} else if (sum.apply(null, args) !== 5050) {
    alert('测试失败: sum(1, 2, 3, ..., 100) = ' + sum.apply(null, args));
} else {
    alert('测试通过!');
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值