函數(shù)聲明和函數(shù)表達式有什么區(qū)別
函數(shù)聲明:
function name(params) {
console.log("say hello~");
}
函數(shù)表達式:
var sayHello = function(params) {
console.log("say hello~");
}
JavaScript 解釋器中存在一種變量聲明被提升的機制郑临,也就是說函數(shù)聲明會被提升到作用域的最前面对省,即使寫代碼的時候是寫在最后面,也還是會被提升至最前面盾似。
而用函數(shù)表達式創(chuàng)建的函數(shù)是在運行時進行賦值隘竭,且要等到表達式賦值完成后才能調(diào)用
什么是變量的聲明前置滤祖?什么是函數(shù)的聲明前置
變量的前置聲明:JavaScript引擎的工作方式是,先解析代碼棍潘,獲取所有被聲明的變量恃鞋,然后再一行一行地運行。這造成的結(jié)果亦歉,就是所有的變量的聲明語句恤浪,都會被提升到代碼的頭部,然后給他初始值undefined肴楷,然后才逐句執(zhí)行程序水由,這就叫做“變量提升”,也即“變量的聲明前置”赛蔫。
函數(shù)的聲明前置JavaScript引擎將函數(shù)名視同變量名砂客,所以采用function聲明函數(shù)時,整個函數(shù)會像var聲明變量一樣濒募,被提升到代碼頭部
arguments 是什么
arguments是一個類數(shù)組對象, 代表傳給一個function的參數(shù)列表, 只在函數(shù)內(nèi)部起作用; arguments的值與函數(shù)傳入?yún)?shù)有關(guān), 與定義參數(shù)無關(guān)鞭盟。
可以使用arguments對象在函數(shù)中引用函數(shù)的參數(shù)。此對象包含傳遞給函數(shù)的每個參數(shù)的條目瑰剃,第一個條目的索引從0開始齿诉。例如,如果一個函數(shù)傳遞了三個參數(shù),你可以以如下方式引用他們:
arguments[0]
arguments[1]
arguments[2]
參數(shù)也可以被設(shè)置:
arguments[1] = 'new value';
arguments對象不是一個 Array 粤剧。它類似于Array歇竟,但除了長度之外沒有任何Array屬性
arguments.callee
指向當前執(zhí)行的函數(shù)。
arguments.caller
指向調(diào)用當前函數(shù)的函數(shù)抵恋。
arguments.length
指向傳遞給當前函數(shù)的參數(shù)數(shù)量焕议。
arguments[@@iterator]
返回一個新的Array迭代器對象,該對象包含參數(shù)中每個索引的值弧关。
函數(shù)的"重載"怎樣實現(xiàn)
根據(jù)函數(shù)內(nèi)建變量arguments的length屬性來實現(xiàn):
function overLoading() {
// 根據(jù)arguments.length盅安,對不同的值進行不同的操作
switch(arguments.length) {
case 0:
/*操作1的代碼寫在這里*/
break;
case 1:
/*操作2的代碼寫在這里*/
break;
case 2:
/*操作3的代碼寫在這里*/
//后面還有很多的case......
}
}
立即執(zhí)行函數(shù)表達式是什么?有什么作用
在定義函數(shù)之后世囊,立即調(diào)用該函數(shù), 為了避免function出現(xiàn)在行首, 引起JS解析錯誤, 讓JS引擎將其理解成一個表達式,這就叫做"立即執(zhí)行的函數(shù)表達式
常見的實現(xiàn)如下:
(function name() {
do something;
})();
(function wahah() {
console.log('wahahah');
}());
var aa = function() {
console.log("wahha");
}();
主要用于隔絕作用域别瞭。因為其創(chuàng)建了一個新的函數(shù)作用域,從而不去污染全局命名空間株憾。
求n!蝙寨,用遞歸來實現(xiàn)
function n(x) {
if(x < 2){
return 1;
}else if(x < 0){
return
}
else {
return x * arguments.callee(x - 1);
}
}
以下代碼輸出什么?
function getInfo(name, age, sex){
console.log('name:',name);
console.log('age:', age);
console.log('sex:', sex);
console.log(arguments);
arguments[0] = 'valley';
console.log('name', name);
}
輸出結(jié)果:
getInfo('饑人谷', 2, '男');
name: 饑人谷
age: 2
sex: 男
{ '0': '饑人谷', '1': 2, '2': '男' }
name valley
getInfo('小谷', 3);
name: 小谷
age: 3
sex: undefined
{ '0': '小谷', '1': 3 }
name valley
getInfo('男');
name: 男
age: undefined
sex: undefined
{ '0': '男' }
name valley
寫一個函數(shù)實現(xiàn)返回參數(shù)的平方和
function sumOfSquares() {
var res = 0;
for (var i = 0; i < arguments.length; i++) {
res += arguments[i] * arguments[i];
}
return res;
}
var sum = sumOfSquares(1,2);
console.log(sum);
如下代碼的輸出嗤瞎?為什么
console.log(a); //undefined, 變量聲明會前置墙歪,并賦值undefined
var a = 1;
console.log(b); //報錯, b未聲明
如下代碼的輸出?為什么
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
第二行報錯是因為sayAge是函數(shù)表達式贝奇,而函數(shù)表達式要先聲明后調(diào)用
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
輸出: x = 10
作用域鏈查找偽代碼:
globalContext = {
ActiveObject:{
x:10
foo:function
bar:fucntion
}
scope: null
}
聲明foo: foo.[[scope]] = globalContext.ActiveObject
聲明bar: bar.[[scope]] = globalContext.ActiveObject
barContext = {
ActiveObject:{
x:30
foo:function
}
scope: globalContext.ActiveObject
}
fooContext = {
ActiveObject: {
}
scope: globalContext.ActiveObject
}
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
輸出: x = 30
作用域鏈查找:
globalContext = {
ActiveObject:{
x:10
bar:function
}
scope: null
}
barContext = {
ActiveObject:{
x:30
foo:function
}
scope:globalContext.ActiveObject
}
fooContext = {
ActiveObject:{
}
scope: barContext.ActiveObject
}
以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
輸出: x = 30
作用域鏈查找:
globalContext = {
AO: {
x: 10
bar:function
}
scope: null
}
bar.[[scope]] = globalContext.AO
barContext = {
AO: {
x: 30
function
}
scope = globalContext.AO
}
function.[[scope]] = barContext.AO
functionContext = {
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()
console.log(a)
輸出: undefind 5 1 6 20 200
作用域鏈查找:
globalContext = {
ActiveObject:{
a: 200
fn:function(){}
fn3:function(){}
}
scope: null
}
fn.[[scope]] = globalContext.ActiveObject
fn3.[[scope]] = globalContext.ActiveObject
fnContext = {
ActiveObject:{
a: 20
fn2: function(){}
}
scope: globalContext.ActiveObject
}
fn2.[[scope]] = fnContext.ActiveObject
fn3Context = {
ActiveObject:{}
scope: globalContext.ActiveObject
}
fn2Context = {
ActiveObject:{}
scope: fnContext.ActiveObject
}