JavaScript 函數(shù)定義
JavaScript 使用關(guān)鍵字 function 定義函數(shù)坷牛。
函數(shù)可以通過聲明定義亲桥,也可以是一個(gè)表達(dá)式轩娶。
函數(shù)聲明
function functionName(parameters) {
? 執(zhí)行的代碼
}
函數(shù)聲明后不會(huì)立即執(zhí)行魄缚,會(huì)在我們需要的時(shí)候調(diào)用到。
實(shí)例
function myFunction(a, b) {
? ? return a * b;
}
分號是用來分隔可執(zhí)行JavaScript語句喜滨。
由于函數(shù)聲明不是一個(gè)可執(zhí)行語句捉捅,所以不以分號結(jié)束。
函數(shù)表達(dá)式
JavaScript 函數(shù)可以通過一個(gè)表達(dá)式定義虽风。
函數(shù)表達(dá)式可以存儲(chǔ)在變量中:
實(shí)例
var x = function (a, b) {return a * b};
在函數(shù)表達(dá)式存儲(chǔ)在變量后棒口,變量也可作為一個(gè)函數(shù)使用:
實(shí)例
var x = function (a, b) {return a * b};
var z = x(4, 3)
以上函數(shù)實(shí)際上是一個(gè) 匿名函數(shù) (函數(shù)沒有名稱)。
函數(shù)存儲(chǔ)在變量中辜膝,不需要函數(shù)名稱无牵,通常通過變量名來調(diào)用。
上述函數(shù)以分號結(jié)尾厂抖,因?yàn)樗且粋€(gè)執(zhí)行語句茎毁。
Function() 構(gòu)造函數(shù)
在以上實(shí)例中,我們了解到函數(shù)通過關(guān)鍵字 function 定義忱辅。
函數(shù)同樣可以通過內(nèi)置的 JavaScript 函數(shù)構(gòu)造器(Function())定義七蜘。
實(shí)例
var myFunction = new Function("a", "b", "return a * b");
var x = myFunction(4, 3);
實(shí)際上,不必使用構(gòu)造函數(shù)墙懂。上面實(shí)例可以寫成:
實(shí)例
var myFunction = function (a, b) {return a * b};
var x = myFunction(4, 3);
在 JavaScript 中橡卤,很多時(shí)候,需要避免使用 new 關(guān)鍵字损搬。
函數(shù)提升(Hoisting)
提升(Hoisting)是 JavaScript 默認(rèn)將當(dāng)前作用域提升到前面去的的行為碧库。
提升(Hoisting)應(yīng)用在變量的聲明與函數(shù)的聲明。
因此巧勤,函數(shù)可以在聲明之前調(diào)用:
myFunction(5);
function myFunction(y) {
? ? return y * y;
}
使用表達(dá)式定義函數(shù)時(shí)無法提升嵌灰。
自調(diào)用函數(shù)
函數(shù)表達(dá)式可以 "自調(diào)用"。
自調(diào)用表達(dá)式會(huì)自動(dòng)調(diào)用踢关。
如果表達(dá)式后面緊跟 () 伞鲫,則會(huì)自動(dòng)調(diào)用。
不能自調(diào)用聲明的函數(shù)签舞。
通過添加括號秕脓,來說明它是一個(gè)函數(shù)表達(dá)式:
實(shí)例
(function () {
? ? var x = "Hello!!";? ? ? // 我將調(diào)用自己
})();
以上函數(shù)實(shí)際上是一個(gè) 匿名自我調(diào)用的函數(shù) (沒有函數(shù)名)。
函數(shù)可作為一個(gè)值使用
JavaScript 函數(shù)作為一個(gè)值使用:
function myFunction(a, b) {
? ? return a * b;
}
var x = myFunction(4, 3);
JavaScript 函數(shù)可作為表達(dá)式使用:
實(shí)例
function myFunction(a, b) {
? ? return a * b;
}
var x = myFunction(4, 3) * 2;
函數(shù)是對象
在 JavaScript 中使用 typeof 操作符判斷函數(shù)類型將返回 "function" 儒搭。
但是JavaScript 函數(shù)描述為一個(gè)對象更加準(zhǔn)確吠架。
JavaScript 函數(shù)有 屬性 和 方法。
arguments.length 屬性返回函數(shù)調(diào)用過程接收到的參數(shù)個(gè)數(shù):
實(shí)例
function myFunction(a, b) {
? ? return arguments.length;
}
toString() 方法將函數(shù)作為一個(gè)字符串返回:
實(shí)例
function myFunction(a, b) {
? ? return a * b;
}
var txt = myFunction.toString();
函數(shù)定義作為對象的屬性搂鲫,稱之為對象方法傍药。
函數(shù)如果用于創(chuàng)建新的對象,稱之為對象的構(gòu)造函數(shù)魂仍。
箭頭函數(shù)
ES6 新增了箭頭函數(shù)拐辽。
箭頭函數(shù)表達(dá)式的語法比普通函數(shù)表達(dá)式更簡潔。
(參數(shù)1, 參數(shù)2, …, 參數(shù)N) => { 函數(shù)聲明 }
(參數(shù)1, 參數(shù)2, …, 參數(shù)N) => 表達(dá)式(單一)
// 相當(dāng)于:(參數(shù)1, 參數(shù)2, …, 參數(shù)N) =>{ return 表達(dá)式; }
當(dāng)只有一個(gè)參數(shù)時(shí)擦酌,圓括號是可選的:
(單一參數(shù)) => {函數(shù)聲明}
單一參數(shù) => {函數(shù)聲明}
沒有參數(shù)的函數(shù)應(yīng)該寫成一對圓括號:
() => {函數(shù)聲明}
實(shí)例
// ES5
var x = function(x, y) {
? ? return x * y;
}
// ES6
const x = (x, y) => x * y;
有的箭頭函數(shù)都沒有自己的 this俱诸。 不適合頂一個(gè) 對象的方法。
當(dāng)我們使用箭頭函數(shù)的時(shí)候赊舶,箭頭函數(shù)會(huì)默認(rèn)幫我們綁定外層 this 的值睁搭,所以在箭頭函數(shù)中 this 的值和外層的 this 是一樣的。
箭頭函數(shù)是不能提升的笼平,所以需要在使用之前定義园骆。
使用 const 比使用 var 更安全,因?yàn)楹瘮?shù)表達(dá)式始終是一個(gè)常量寓调。
如果函數(shù)部分只是一個(gè)語句锌唾,則可以省略 return 關(guān)鍵字和大括號 {},這樣做是一個(gè)比較好的習(xí)慣:
實(shí)例
const x = (x, y) => { return x * y }
this:
首先要知道this的是在代碼執(zhí)行的時(shí)候才能確定的夺英,定義的時(shí)候不能確定鸠珠,因?yàn)閠his是執(zhí)行上下文的一部分,而執(zhí)行上下文是在代執(zhí)行的時(shí)候才能8定的秋麸。實(shí)際上this的最終指向的是那個(gè)調(diào)用它的對象渐排。想理解this先看幾個(gè)例子:
var a = {
name:'A',
fn: funcrion(){
console.log(this.name);
console.log(this);
}
}
a.fn();//this.name === 'A'; this===a
a.fn.call({name:'B'});//this.name===='B'; this==={name:'B'}
var fn1 = a.fn;
fn1();//this.name === undefined; this===window
通過上面的例子可以看出this的執(zhí)行會(huì)有不同,主要集中在以下幾種情況:1.作為構(gòu)造函數(shù)執(zhí)行灸蟆,在構(gòu)造函數(shù)中(上面例子未體現(xiàn))2.作為對象屬性執(zhí)行驯耻,上述代碼中的a.fn();3.作為普通函數(shù)執(zhí)行,上述代碼中fn1();4.用于call炒考,apply可缚,bind,上述代碼中a.fn.call({name:'B'})斋枢;
其中fn1() 的執(zhí)行結(jié)果有些出乎意料帘靡,上文說過‘實(shí)際上this的最終指向的是那個(gè)調(diào)用它的對象’,fn1中this為什么指向了window瓤帚?繼續(xù)來看例子:
function a() {
var user = "例子";
console.log(this.user);//undefined
console.log(this);//window
}
a();
按照我們上面說的this最終指向的是調(diào)用它的對象描姚,這里的函數(shù)a實(shí)際是被Window對象所點(diǎn)出來的涩赢,下面的代碼就可以證明:
function a() {
var user = "例子";
console.log(this.user);//undefined
console.log(this);//window
}
window.a();
繼續(xù)看例子:
var o = {
user: "例子",
fn: function(){
console.log(this.user);//'例子'
console.log(this);// o
}
}
o.fn(); ==>window.o.fn()
o.fn();等價(jià)于window.o.fn(),但是this并沒有指向window轩勘,而是指向O對象筒扒;是不是有些迷惑,繼續(xù)看例子:
var o = {
a = 10;
b : {
a:12;
fn:function(){
console.log(this.a);//12
console.log(this);//b
}
}
}
o.b.fn();
同樣屬性都是對象o調(diào)用出來的绊寻,但同樣this沒有指向O花墩。其實(shí)我們需要知道以下幾點(diǎn):
1.如果一個(gè)函數(shù)中有this,但是沒有被上一級對象調(diào)用澄步,那么this就指向window冰蘑,嚴(yán)格模式下t'his將指向undefined;2.如果一個(gè)函數(shù)中有this村缸,這個(gè)函數(shù)被上一級對象調(diào)用祠肥,那么this指向上一級對象;3.如果函數(shù)中有this王凑,這個(gè)函數(shù)中包含多個(gè)對象搪柑,盡管這個(gè)函數(shù)是被最外層的對象所調(diào)用,this指向的也是其上一級對象索烹。(上面的例子中工碾,將b對象的值注銷既可以驗(yàn)證)
var o = {
a = 10;
b : {
//a:12;
fn:function(){
console.log(this.a);//undefined
console.log(this);//b
}
}
}
o.b.fn();
還有個(gè)特殊的例子:
var o = {
a = 10;
b : {
a:12;
fn:function(){
console.log(this.a);//undefined
console.log(this);//window;
}
}
}
var c = o.b.fn;
c();
this指向的是最后調(diào)用它的對象,也就是看它執(zhí)行的時(shí)候是誰調(diào)用的百姓,這個(gè)例子中雖然函數(shù)fn是被對象b所引用渊额,但是在將fn賦值給變量c的時(shí)候并沒有執(zhí)行所以最終指向的是window。
在構(gòu)造函數(shù)中this指向也會(huì)不同:
function Fn(){
this.user = '例子';
}
var a = new Fn();
console.log(a.user)//'例子'
這里a可以調(diào)用到user的值垒拢,因?yàn)闃?gòu)造函數(shù)new關(guān)鍵字改變了this的指向旬迹,所以將this指向a。
當(dāng)this遇到return時(shí)結(jié)果也會(huì)有差異,如下面的連個(gè)例子:
function Fn(){
this.user = '例子';
return {};
}
var a = new Fn();
console.log(a.user)//undefined
function Fn(){
this.user = '例子';
return 1;
}
var a = new Fn();
console.log(a.user)//'例子'
#####總結(jié): 如果返回值是一個(gè)對象求类,那么this指向返回的這個(gè)對象奔垦,如果返回值不是一個(gè)對象,那么this還是指向函數(shù)的實(shí)例尸疆;null也是一個(gè)對象椿猎,但是null比較特殊,返回值是null寿弱,this還是指向函數(shù)的實(shí)例犯眠。
css實(shí)現(xiàn)兩欄布局的總結(jié):
兩欄布局(左側(cè)寬度固定,右側(cè)自適應(yīng))症革,在學(xué)習(xí)的過程中總結(jié)了幾種方法:
方法一:float+margin-left
HTML部分
<div class="left">
<h1>Left Side</h1>
<p>我是左側(cè)欄</p>
</div>
<div class="right">
<h1>Right Side</h1>
<p>我是右側(cè)欄</p>
</div>
CSS部分
{
/清除默認(rèn)格式/
margin:0;
padding:0筐咧;
}
.left{
width:200px;
background-color:red;
float:left;
}
.right{
background-color:green;
margin-left:200px;//等于左邊欄的寬度
}
方法二:absolute+margin-leftCSS部分
{
margin:0;
padding:0;
}
.left{
width:100px;
background-color:red;
position:absolute;
}
.right{
background-color:green;
margin-left:100px;
}
方法三:float+BFC為左側(cè)元素設(shè)置浮動(dòng)后,左側(cè)元素會(huì)因?yàn)楦?dòng)蓋在右側(cè)元素上,因此要將右側(cè)元素變成BFC量蕊,BFC是一個(gè)獨(dú)立的區(qū)域铺罢,不會(huì)讓BFC外的元素對其內(nèi)部造成干擾。當(dāng)右側(cè)元素變成一個(gè)BFC時(shí)它的元素邊界會(huì)發(fā)生變化危融,會(huì)緊緊貼合左側(cè)的元素畏铆。常見的右側(cè)元素設(shè)置----overflow:hidden雷袋;
方法四:flex布局HTML部分
<div class="box">
<div class="left">
<h1>Left Side</h1>
<p>我是左側(cè)欄</p>
</div>
<div class="right">
<h1>Right Side</h1>
<p>我是右側(cè)欄</p>
</div>
</div>
CSS設(shè)置:
{
/清除默認(rèn)格式/
margin:0;
padding:0;
}
.box{
display:flex;
}
.box1{
}
.box2{
flex:1;
}