-
函數聲明和函數表達式有什么區別?
函數聲明和函數表達式是EMACScript規定的兩種不同的聲明函數的方法。
1.函數聲明
//聲明函數
function name() { //function+函數名+(參數)+{函數體}
console.log ('Jack')
}
//函數調用
name()
函數聲明會在JavaScript代碼開始時提到最前面進行定義,因此函數聲明不必在調用之前定義。
2.函數表達式
var name = function () {
console.log ('Jack')
}
雖然變量聲明會提到JavaScript代碼開始前,但是賦值要運行到該行代碼才執行,因此在調用用函數表達式聲明的函數時,聲明必須放到調用前。
總結區別:
1.函數聲明會在代碼開始前定義,函數表達式遇到時才會執行。
2.函數聲明必須有函數名,函數表達式則可以省略。
-
什么是變量的聲明前置?什么是函數的聲明前置?
變量聲明前置:
JavaScript的工作方式是先解析代碼,獲取一個作用域下所有的變量聲明,放到代碼開頭聲明,再一行行的執行代碼:
var a = 10;
var b = 20;
//等同于下面代碼;
var a,b; //將聲明提前,聲明ab。ab的值都是undefined。
a = 10; //a賦值為10,此時a=10;
b = 20; //b賦值為20,此時b=20;
函數聲明前置:
函數聲明前置與變量聲明前置類似,JavaScript工作是會獲取一個作用域下的所有函數聲明,放在代碼開始前進行定義。如果使用的是函數表達式,則規則與變量聲明前置類似:
var name = function () {
console.log ('Jack')
}
//等同于
var name;
name = function () {
console.log ('Jack')
}
-
arguments是什么?
在ECMAScript中,函數的參數在內部是用一個數組來表示的。在函數體內,可以用arguments來訪問這個參數數組。arguments是一個類數組對象(不是Array的實例),因為可以使用方括號語法訪問它的每一個元素,使用length屬性來確定傳遞進來多少參數,示例:
function test () {
console.log (arguments.length); //參數的長度
console.log (arguments[0]); //第一個參數
console.log (arguments[1]); //第二個參數
}
test ('Jack',1,'888');
//輸出結果為 3,'Jack',1
-
JS函數的"重載"怎樣實現?
重載,是函數或者方法有相同的名稱,但是參數列表不相同的情形,這樣的同名不同參數的函數或者方法之間,互相稱之為重載函數或者方法。但是在JS,并沒有重載這個概念,但我們可以用另外一種方法實現這個功能:
function test (num) {
if (num>=90) {
console.log ('優秀')
}
if (num>=60&&num<90) {
console.log ('及格')
}
if (num<60) {
console.log ('不及格')
}
}
test(95) //輸出 '優秀'
test(77) //輸出 '及格'
test(18) //輸出 '不及格'
這樣對于同一個函數,輸入不同參數就會得到不同結果。
-
立即執行函數表達式是什么?有什么作用?
在JS中我們可以使用函數聲明和函數表達式聲明函數,再通過函數名進行調用:
function sayName (name) { //函數聲明聲明函數
console.log (name);
}
sayName ('Jack'); // 調用函數
var sayName = function () { //函數表達式聲明函數
console.log (name);
}
sayName ('Jack') // 調用函數
因為在JS中圓括號()內是不能有語句的,括號內容會被當做表達式,因此上面例子可以進行改寫:
(function (name) {
console.log (name);
})('Jack')
//或者
(function (name) {
console.log (name);
}('Jack')) // 輸出都為Jack
當JS執行到該行代碼時,函數會被定義且立即執行,叫做立即執行函數表達式。
使用立即執行函數表達式可以創建一個獨立的作用域,形成隔離,避免污染全局。
-
求n!,用遞歸來實現
function test (n) {
if (n===1) {
return 1;
}
return n*test(n-1)
}
test (10); //3628800
-
以下代碼輸出什么?
function getInfo(name, age, sex){
console.log('name:',name);
console.log('age:', age);
console.log('sex:', sex);
console.log(arguments); //輸出整組參數;
arguments[0] = 'valley'; //第一個參數賦值為‘valley’;
console.log('name', name);
}
getInfo('饑人谷', 2, '男');
// name:饑人谷,age:2,sex:男,['饑人谷',2,'男'],name valley;
getInfo('小谷', 3);
// name:小谷,age:3,sex:undefined,['小谷',3],name valley;
getInfo('男');
// name:男,age:undefined,sex:undefined,['男'],name valley;
-
寫一個函數,返回參數的平方和
function test (n) {
if (n===1) {
return 1
}
return n*n+test(n-1)*text(n-1)
}
test (2) //5
-
解釋下列代碼的輸出及原因
console.log(a); // 由于聲明提前,此時a未賦值,輸出undefined;
var a = 1; // a=1;
console.log(b); //報錯,b未被聲明;
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
//解釋
function sayName(name){ //函數聲明和變量聲明提前;
console.log('hello ', name);
}
var sayAge;
sayName('world'); //調用函數,輸出'hello,world';
sayAge(10); //undefined,因為sayAge未定義;
sayAge = function(age){
console.log(age);
};
//函數表達式需放到調用前!!
-
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
} // 輸出 10;
/*
作用域查找過程
goblecontext = {
AO: {
X=10
foo: function
bar: function
}
foo.[[scope]]: goblecontext.AO
bar.[[scope]]: goblecontext.AO
}
foocontext = {
AO: {}
scope: goblecontext.AO
}
barcontext = {
AO: {
x = 30
}
scope: goblecontext.AO
}
*/
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
} //輸出30
/*
作用域查找過程
goblecontext = {
AO: {
x=10
bar:function
}
bar.[[scopr]]=goblecontext.AO
}
barcontext = {
AO: {
x=30
foo:function
}
foo.[[scope]]=barcontext.AO
scope=goblecontext.AO
}
foocontext = {
AO: {}
scope=barcontext.AO
}
*/
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
} //輸出30
/*
作用域查找
goblecontext = {
AO: {
x=10
bar:function
}
bar.[[scope]]=goblecontext.AO
scope=null
}
barcontext = {
AO: {
x=30
f:function
}
f.[[scope]]=barcontext.AO
scope=goblecontext.AO
}
fcontext = {
AO: {}
scope=barcontext.AO
}
*/
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() //輸出:undefined,5,1,6,20,200;
console.log(a)
/*
goblecontext = {
AO: {
a: undefined
fn: function
fn3: function
}
scope = null
fn.[[scope]] = goblecontext.AO
fn3.[[scope]] = goblecontext.AO
}
fncontext = {
AO: {
a: undefinef
fn2: function
}
scope = goblecontext.AO
fn2.[[scope]] = fncontext.AO
}
fn2context = {
AO: {
a: 20
}
scope = fncontext.AO
}
fn3context = {
AO: {
a: 200
}
scope = goblecontext.AO
}
*/
遇到fn(),開始執行:
console.log(a),,此時fncontextAO中a未被賦值,輸出undefined;
a = 5;
console.log(a),此時fncontextAO中a被賦值為5,輸出5;
a++,fncontextAO中a變為6;
var a,因為a已經存在,故無意義;
fn3(),執行fn3(),進入fn3context;
console.log(a),goblecontextAO中,a=1,故輸出1;
a=200,goblecontextAO中a變為200;
fn2,執行fn2(),進入fn2context;
console.log(a),fncontextAO中,a=6,故輸出6;
a=20,fncontextAO中,a變為20;
console.log(a),fncontextAO中,a為20,故輸出20;
fn執行完畢;
console.log(a),goblecontextAO中,a為200,故輸出200;