函数与作用域
2017-06-22 本文已影响0人
山门龙龙
1.函数声明和函数表达式有什么区别
- 函数声明使用function关键字进行声明,声明不必放到调用的前面。因为函数可以函数声明前置。函数声明的时候函数并没有被执行。
- 函数表达式是将函数赋值给一个变量,声明必须放到调用的前面。因为变量虽然也可以声明前置,但是因为变量声明前置的时候只是变量被前置,变量并没有被赋值,所以声明要放到调用前面,变量才有用。
2.什么是变量的声明前置?什么是函数的声明前置
- 变量的声明前置就是将变量在变量所处的作用域内依次放在最前面进行声明,但不赋值。声明完之后,再依次执行JS语句。
- 函数的声明前置同变量一样,将函数在函数所处的作用域内依次放在最前面进行声明,但不执行该函数。声明完之后,再依次执行JS语句。
- 本质上变量的声明前置和函数的声明前置没什么区别,都是先声明,再使用。
3.arguments 是什么
arguments是函数的形参,它是一个类数组对象。比如:
function(name,age,sex){
name = "man";
age = 20;
arguments[2] = 1;
}
arguments[2]就是形参sex,他是函数的一个默认的形参,它可以方便的调用形参。
4.函数的"重载"怎样实现
- JS中不存在函数的“重载”,同名函数会被覆盖,但是JS却可以利用函数体针对不同的参数调用相应的逻辑来达到其他语言的函数重载的效果。
- 其他语言的函数重载样例:
function int translateNumber(parseInt(a),parseInt(b)){
statement;
}
function float translateNumber(parseFloat(a),parseFloat(b)){
statement;
}
- JS伪"重载"样例:
function getInfOfPeople(name,age,sex) {
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
getInfOfPeople(2,3);
getInfOfPeople(2,3,1);
5.立即执行函数表达式是什么?有什么作用
- ()表示是一个表达式,而形如(function(){})()就是一个立即执行的函数表达式,他将函数禁锢在表达式内,它不会有声明前置,而是在加载到它的时候立刻执行。
- 它的作用就是为了保护他的变量不被污染,它的变量的作用域只会在函数内。
6.求n!,用递归来实现
function getfactorial(n) {
if(n === 1){
return 1;
}else if(n > 1){
return n * getfactorial(n-1);
}else{
console.log("您的输入有误!请输入大于1的整数");
}
}
console.log(getfactorial(5));
输出结果120,递归的特点:
1.调用自身
2.有中止条件
3.算法简单
4.效率较低
7.以下代码输出什么?
7.png- 第一个getInfo()中name='饥人谷' , age=2 ,sex='男' 输出为:
name: 饥人谷
age: 2
sex: 男
arguments[0]: "valley"
arguments[1]: 2
arguments[2]: "男"
name valley
- 第二个getInfo()中name='小谷' , age=3 输出为:
name: 小谷
age: 3
sex: undefined
arguments[0]: "valley"
arguments[1]: 2
name valley
- 第三个getInfo()中name='男' 输出为:
name: 男
age: undefined
sex: undefined
arguments[0]: 'valley'
name valley
8.写一个函数,返回参数的平方和?
function sumOfSquares(){
var result =0;
for(var i=0;i<arguments.length;i++){
result += arguments[i] * arguments[i];
}
return result;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
9.如下代码的输出?为什么
console.log(a);
var a = 1;
console.log(b);
变量a声明前置,但未赋值,所以console.log(a);
输出undefined,然后变量b未声明,所以报错,提示变量b未被声明。
10.如下代码的输出?为什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
输出hello world,sayAge() is not a function,这个考的是函数声明和函数表达式的区别。函数声明无需遵守顺序,只要在同一作用域内,都可以被调用。而函数表达式必须放在调用之前,因为JS文档是从上到下依次加载的,函数表达式就相当于声明了一个变量,把函数赋值在变量内,本质上还是声明一个变量,所以必须放在前面。sayName()是函数声明,sayAge()是函数表达式,所以结果就是上面所说的情况。
11.如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
作用域链伪代码:
/*
globalContext = {
AO: {
x: 10
foo(): function(){}
bar(): function(){}
}
}
bar.[[scope]] = globalContext.AO
fooContext = {
AO: {
x: undefined
}
scope: globalContext.AO
}
barContext{
AO: {
x: 30
foo(): function(){}
}
scope: globalContext.AO
}
*/
12. 如下代码输出什么? 写出作用域链查找过程伪代码
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
作用域链伪代码:
/*
globalContext = {
AO: {
x: 10
bar(): function(){}
}
}
bar.[[scope]] = globalContext.AO
barContext = {
AO: {
x: 30
foo(): function(){}
}
scope: globalContext.AO
}
foo.[[scope]] = barContext.AO
fooContext = {
AO: {
x: undefined
}
scope: barContext.AO
}
*/
13.以下代码输出什么? 写出作用域链的查找过程伪代码
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
作用域链伪代码:
/*
globalContext = {
AO: {
x: 10
bar(): function(){}
}
}
bar.[[scope]] = globalContext.AO
barContext = {
AO: {
x: 30
}
scope: globalContext.AO
}
*/
14.以下代码输出什么? 写出作用域链查找过程伪代码
var a = 1;
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn3()
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)
作用域链伪代码:
/*
globalContext = {
AO: {
a: 1
fn: function(){}
fn3: function(){}
}
}
fn.[[scope]] = globalContext.AO
fnContext = {
AO: {
a: 6
fn2(): function(){}
}
scope: globalContext.AO
}
fn2.[[scope]] = fnContext.AO
fn3.[[scope]] = fnContext.AO
fn2Context = {
AO: {
a: 20
}
scope: fnContext.AO
}
fn3Context = {
AO: {
a: 200
}
scope: globalContext.AO
}
*/