-
函數聲明和函數表達式有什么區(qū)別宵睦?
函數聲明和函數表達式是EMACScript規(guī)定的兩種不同的聲明函數的方法槐臀。
1.函數聲明
//聲明函數
function name() { //function+函數名+(參數)+{函數體}
console.log ('Jack')
}
//函數調用
name()
函數聲明會在JavaScript代碼開始時提到最前面進行定義,因此函數聲明不必在調用之前定義。
2.函數表達式
var name = function () {
console.log ('Jack')
}
雖然變量聲明會提到JavaScript代碼開始前,但是賦值要運行到該行代碼才執(zhí)行,因此在調用用函數表達式聲明的函數時亿卤,聲明必須放到調用前。
總結區(qū)別:
1.函數聲明會在代碼開始前定義鹿霸,函數表達式遇到時才會執(zhí)行排吴。
2.函數聲明必須有函數名,函數表達式則可以省略懦鼠。
-
什么是變量的聲明前置傍念?什么是函數的聲明前置?
變量聲明前置:
JavaScript的工作方式是先解析代碼葛闷,獲取一個作用域下所有的變量聲明憋槐,放到代碼開頭聲明,再一行行的執(zhí)行代碼:
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工作是會獲取一個作用域下的所有函數聲明阱飘,放在代碼開始前進行定義斥杜。如果使用的是函數表達式虱颗,則規(guī)則與變量聲明前置類似:
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 ('優(yōu)秀')
}
if (num>=60&&num<90) {
console.log ('及格')
}
if (num<60) {
console.log ('不及格')
}
}
test(95) //輸出 '優(yōu)秀'
test(77) //輸出 '及格'
test(18) //輸出 '不及格'
這樣對于同一個函數床估,輸入不同參數就會得到不同結果含滴。
-
立即執(zhí)行函數表達式是什么?有什么作用丐巫?
在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執(zhí)行到該行代碼時碑韵,函數會被定義且立即執(zhí)行,叫做立即執(zhí)行函數表達式缎脾。
使用立即執(zhí)行函數表達式可以創(chuàng)建一個獨立的作用域祝闻,形成隔離,避免污染全局遗菠。
-
求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);
};
//函數表達式需放到調用前6鞲ぁ畔塔!
-
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
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(),開始執(zhí)行:
console.log(a),,此時fncontextAO中a未被賦值沾鳄,輸出undefined译荞;
a = 5;
console.log(a)吞歼,此時fncontextAO中a被賦值為5塔猾,輸出5丈甸;
a++睦擂,fncontextAO中a變?yōu)?;
var a淘正,因為a已經存在鸿吆,故無意義惩淳;
fn3(),執(zhí)行fn3()恕刘,進入fn3context褐着;
console.log(a)含蓉,goblecontextAO中馅扣,a=1着降,故輸出1任洞;
a=200交掏,goblecontextAO中a變?yōu)?00盅弛;
fn2,執(zhí)行fn2()见秽,進入fn2context解取;
console.log(a)肮蛹,fncontextAO中伦忠,a=6,故輸出6气忠;
a=20旧噪,fncontextAO中淘钟,a變?yōu)?0米母;
console.log(a)毡琉,fncontextAO中桅滋,a為20芍碧,故輸出20笋鄙;
fn執(zhí)行完畢萧落;
console.log(a)找岖,goblecontextAO中许布,a為200蜜唾,故輸出200袁余;