◆
JavaScript 函数声明、属性与参数传递详解
函数声明
function命令
function fnn(name) {
console.log(name);
}
- 函数表达式
const fnn = function (name) {
console.log(name);
};
注意点
函数表达式的写法相当于将一个匿名函数赋值给变量。 函数表达式声明的函数,
function命令后面不带有函数名。如果加上函数名, 该函数名只在函数体内部有效,在函数体外部无效
const fnn = function fx(name) {
console.log(name);
console.log(fx);
};
/**
输出 fnn 以及
ƒ fx(name) {
console.log(name);
console.log(fx);
}
*/
fnn('fnn');
// Uncaught ReferenceError: fx is not defined
fx('fx');
加入函数名出现报错,有函数名称则显示函数名称
const fnn = function (name) {
console.log(name);
throw Error(1);
};
fnn('fnn');
// 控制台报错测试
const fnn = function fx(name) {
console.log(name);
throw Error(1);
};
fnn('fnn');
在控制台的显示如下

使用函数名称实现自调用
const fnn = function fx(name) {
console.log(name);
if (name === 'fx') {
return;
}
fx('fx');
};
fnn('fnn');
输出如下

Function构造函数
const fnn = new Function(
'name',
'age',
'sex',
"return 'name:' + name + ' age:' + age + ' sex:' + sex",
);
// name:fx age:18 sex:girl
console.log(fnn('fx', 18, 'girl'));
// 等同于
function copyFnn(name, age, sex) {
return 'name:' + name + ' age:' + age + ' sex:' + sex;
}
const fx = Function(
'name',
'age',
'sex',
"return 'name:' + name + ' age:' + age + ' sex:' + sex",
);
// name:fnn age:18 sex:girl
console.log(fx('fnn', 18, 'girl'));
测试如下

上述代码中 Function 构造函数接受三个参数,除了最后一个参数是 fnn 函数的“函数体”,其他参数都是 fnn 函数的参数。
- 只有最后一个参数会被当做函数体,如果只有一个参数,该参数就是函数体。
Function构造函数可以不使用new命令,输出结果一致
对象中函数的 name 属性
对象方法也是函数,因此也有 name 属性
const person = {
sayName() {
console.log('hello!');
},
};
person.sayName.name;
如果对象的方法使用了取值函数(getter)和存值函数(setter),则 name 属性不是在该方法上面,而是该方法的属性的描述对象的 get 和 set 属性上面,返回值是方法名前加上 get 和 set。
const obj = {
get foo() {},
set foo(x) {},
};
obj.foo.name;
// TypeError: Cannot read property 'name' of undefined
const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
descriptor.get.name; // "get foo"
descriptor.set.name; // "set foo"
有两种特殊情况
bind方法创造的函数,name属性返回bound加上原函数的名字;Function构造函数创造的函数,name属性返回anonymous。
new Function().name; // "anonymous"
var doSomething = function () {
// ...
};
doSomething.bind().name; // "bound doSomething"
如果对象的方法是一个 Symbol 值,那么 name 属性返回的是这个 Symbol 值的描述。
const key1 = Symbol('description');
const key2 = Symbol();
let obj = {
[key1]() {},
[key2]() {},
};
obj[key1].name; // "[description]"
obj[key2].name; // ""
函数提升相关
函数的属性与方法
name属性
function fnn() {}
// fnn
console.log(fnn.name);
var fx = function () {};
// fx
console.log(fx.name);
var wfly = function fly() {};
// fly
console.log(wfly.name);

length属性
函数的
length属性返回函数预期传入的参数个数,即函数定义之中的参数个数
它的 length 属性就是定义时的参数个数。不管调用时输入了多少个参数
function fnn(name, age, sex) {
console.log(fnn.length);
}
// 输出 3
fnn();
toString()方法
返回一个字符串,内容是函数的源码
function fnn(name, age, sex) {
console.log(fnn.length);
}
// 输出函数源码
console.log(fnn.toString());

原生的函数,toString() 方法返回 function (){[native code]}
// 'function isNaN() { [native code] }'
console.log(isNaN.toString());
函数作用域相关
函数参数的省略
如下代码所示,函数调用时省略的参数都是 undefined,如果一定要省略靠前的参数,只有显式传入 undefined。
function fnn(name, age, sex) {
console.log(name, age, sex);
}
// fnn undefined undefined
fnn('fnn');
// undefined 18 undefined
fnn(undefined, '18');
同名参数
如果有同名的参数,则取最后出现的那个值。
function fnn(name, name) {
console.log(name);
}
// undefined
console.log(fnn('fnn'));
// 18
console.log(fnn(undefined, '18'));
值的传递
function fnn(obj, money) {
obj.age = 8;
money = 1000;
}
const messgae = {
name: 'wfly',
age: 18,
};
const num = 100;
fnn(messgae, num);
// {name: 'wfly', age: 8}
console.log(messgae);
// 100
console.log(num);

如上述所示,message 的值被修改了,但是 num 的值没有被修改。
- 函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递。这意味着,在函数体内修改参数值,不会影响到函数外部。
- 如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。
- 如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。 这是因为,形式参数(函数的参数)的值实际是外部参数的地址,重新对形式参数赋值导致形式参数指向另一个地址,保存在原地址上的值当然不受影响。

还没有留言,来发表第一条吧~