2.函数
函数和方法的区别:
- 函数:是可以执行的JavaScript代码块,由JavaScript程序定义或JavaScript实现预定义。
- 方法:是通过对象调用的JavaScript函数。方法也是函数,只是比 较特殊的函数。
实际比较起来,函数和方法差别不大。
2.1 定义函数
以定义绝对值函数为例:
// 定义方法一
function abs(x){
if(x>0){
return x;
}else{
return -x;
}
}
// 定义方法二
var abs = function(x){
if(x>0){
return x;
}else{
return -x;
}
}
// 调用方法
> abs(10)
> abs(-5)
JavaScript 可以传任意个参数也可以不传参数!JS 不会验证传递进来的参数个数是否等于函数定义的参数个数!!
> abs()
NaN // 不传参数也不会报错,返回NaN
> abs(-1, 2, -3, 4, -5)
1 // 传多个参数时,只作用于第一个参数
参数问题
参数传进来是否存在的问题?如果不存在参数,如何规避?
手动抛出异常!!
var abs = function(x){
if (typeof x !== 'number'){
throw 'NaN';
}
if(x>0){
return x;
}else{
return -x;
}
}
arguments 类数组对象
是一个JavaScript免费赠送的关键字,JS把所有传进来的参数都存储在arguments 里面,以数组的形式。
function show() {
console.log(arguments);
}
> show(1, 2, 3, 4, 5)
注:arguments对象不是一个数组。只是类似于array,但除了length属性和索引元素之外没有任何array属性。
// 参数的相加(无论传入多少个参数都可以)
function add() {
var len = arguments.length,
sum = 0;
for(;len--;){
sum += arguments[len];
}
return sum;
}
由于 arguments 包含传进来的所有参数,当我们只想要对多余参数进行操作时怎么办?
rest (ES6)获取除了已经定义的参数之外的所有参数
function show(a, b, ...rest) {
console.log('a+>'+a);
console.log('b+>'+b);
console.log(rest);
}
// 调用
> show(1, 2, 3, 4, 5, 6)
a+>1
b+>2
(5) [3, 4, 5, 6, 7]
2.2 变量的作用域
在JavaScript中, var定义的变量实际是有作用域的。
- 在函数体中声明的变量,函数体外不可以使用(报错)
function show() {
var x =1;
x = x+1;
}
x = x+2; // 报错
- 如果两个函数使用了相同的变量名,只要在函数内部就不冲突
// 内部函数变量重名,没有影响
function aaa() {
var x = 1;
x = x + 1;
}
function bbb() {
var x = 'A';
x = x + 1;
}
// 内部函数可以访问内部函数的成员,反之不行
function aa() {
var x = 1;
function bb() {
var y = x+1;
}
z = y +1; // aa() 报错: y is not defined
}
- 假设内部函数变量与外部函数重名
function aa() {
var x = 1;
function bb() {
var x = 'A'
console.log('inner>'+x);
}
console.log('outer>'+x);
bb()
}
aa()
// 结果
outer>1
inner>A
总结:在 JavaScript 中,函数查找会从自身开始,由内向外查找。假设函数内部存在这个同名变量,则内部函数会屏蔽外部函数的变量。
提升变量的作用域
JavaScript 执行引擎自动提升变量声明,但是不会提升变量的赋值
function aa() {
var x = 'x' + y;
console.log(x);
var y = 'y';
}
aa()
// 结果:xundefined
养成规范1:所有变量的申明和赋值放在代码头部!!先申明后赋值最后调用!!!
全局变量
// 全局变量
var x = 1;
// 默认所有的全局变量都会自动绑定带window对象中
var x = 'aaa';
alert(x);
alert(window.x); // 弹出两次aaa
JavaScript 实际上只有一个全局作用域,任何变量(函数也可视为变量)加入没有在函数范围内找到,就会向外查找;如果函数外也没有找到,就会报错:Reference Error。
由于所有变量都会自动绑定到window上。容易出现不同的JavaScript文件使用了相同的全局变量,导致冲突。
规范2:把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名的冲突,避免绑定到window上
var Only = {};
Only.name = 'cianbei';
Only.add = function (a,b) {
return a+b;
}
> Only.name
"cianbei"
> Only.add(1,2)
3
局部作用域 建议使用 let 定义局部变量
// var定义全局变量
function show() {
for(var i=0; i<100; i++){
console.log(i)
}
console.log(i+1); // 打印101
}
// let定义局部变量
function show() {
for(let i=0; i<100; i++){
console.log(i)
}
console.log(i+1); // 报错:i is not defined
}
常量 const
const pi = 3.14;
pi = 3.15; // 重新赋值会报错
2.3 方法
定义方法
对象只有两个东西:属性和方法。把函数放进对象里就是方法!!
var show = {
// 属性
name: 'xiuer',
birth: 2005,
// 方法
age: function () {
var now = new Date().getFullYear()
return now-this.birth;
}
}
> show.name
"xiuer"
> show.birth
2005
> show.age
ƒ () {
var now = new Date().getFullYear()
return now-this.birth;
}
> show.age() // 调用一定要加括号()
16
this 默认指向调用他所在方法的那个对象
function getage() {
var now = new Date().getFullYear();
return now-this.birth;
}
var show = {
name: 'xiuer',
birth: 2005,
age: getage
}
> show.age()
16
> getage()
NaN
> getage.apply(show,[]) // apply 控制 this 指向
16