JavaScript 函数定义
JavaScript 使用关键字 function 定义函数。
函数可以通过声明定义,也可以是一个表达式。
函数声明
function functionName(parameters) {
执行的代码
}
函数声明后不会立即执行,会在我们需要的时候调用到。
实例
function myFunction(a, b) {
return a * b;
}
分号是用来分隔可执行JavaScript语句。
由于函数声明不是一个可执行语句,所以不以分号结束。
函数表达式
JavaScript 函数可以通过一个表达式定义。
函数表达式可以存储在变量中:
实例
var x = function (a, b) {return a * b};
在函数表达式存储在变量后,变量也可作为一个函数使用:
实例
var x = function (a, b) {return a * b};
var z = x(4, 3)
以上函数实际上是一个 匿名函数 (函数没有名称)。
函数存储在变量中,不需要函数名称,通常通过变量名来调用。
上述函数以分号结尾,因为它是一个执行语句。
Function() 构造函数
在以上实例中,我们了解到函数通过关键字 function 定义。
函数同样可以通过内置的 JavaScript 函数构造器(Function())定义。
实例
var myFunction = new Function("a", "b", "return a * b");
var x = myFunction(4, 3);
实际上,不必使用构造函数。上面实例可以写成:
实例
var myFunction = function (a, b) {return a * b};
var x = myFunction(4, 3);
在 JavaScript 中,很多时候,需要避免使用 new 关键字。
函数提升(Hoisting)
提升(Hoisting)是 JavaScript 默认将当前作用域提升到前面去的的行为。
提升(Hoisting)应用在变量的声明与函数的声明。
因此,函数可以在声明之前调用:
myFunction(5);
function myFunction(y) {
return y * y;
}
使用表达式定义函数时无法提升。
自调用函数
函数表达式可以 "自调用"。
自调用表达式会自动调用。
如果表达式后面紧跟 () ,则会自动调用。
不能自调用声明的函数。
通过添加括号,来说明它是一个函数表达式:
实例
(function () {
var x = "Hello!!"; // 我将调用自己
})();
以上函数实际上是一个 匿名自我调用的函数 (没有函数名)。
函数可作为一个值使用
JavaScript 函数作为一个值使用:
function myFunction(a, b) {
return a * b;
}
var x = myFunction(4, 3);
JavaScript 函数可作为表达式使用:
实例
function myFunction(a, b) {
return a * b;
}
var x = myFunction(4, 3) * 2;
函数是对象
在 JavaScript 中使用 typeof 操作符判断函数类型将返回 "function" 。
但是JavaScript 函数描述为一个对象更加准确。
JavaScript 函数有 属性 和 方法。
arguments.length 属性返回函数调用过程接收到的参数个数:
实例
function myFunction(a, b) {
return arguments.length;
}
toString() 方法将函数作为一个字符串返回:
实例
function myFunction(a, b) {
return a * b;
}
var txt = myFunction.toString();
函数定义作为对象的属性,称之为对象方法。
函数如果用于创建新的对象,称之为对象的构造函数。
箭头函数
ES6 新增了箭头函数。
箭头函数表达式的语法比普通函数表达式更简洁。
(参数1, 参数2, …, 参数N) => { 函数声明 }
(参数1, 参数2, …, 参数N) => 表达式(单一)
// 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
当只有一个参数时,圆括号是可选的:
(单一参数) => {函数声明}
单一参数 => {函数声明}
没有参数的函数应该写成一对圆括号:
() => {函数声明}
实例
// ES5
var x = function(x, y) {
return x * y;
}
// ES6
const x = (x, y) => x * y;
有的箭头函数都没有自己的 this。 不适合顶一个 对象的方法。
当我们使用箭头函数的时候,箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的。
箭头函数是不能提升的,所以需要在使用之前定义。
使用 const 比使用 var 更安全,因为函数表达式始终是一个常量。
如果函数部分只是一个语句,则可以省略 return 关键字和大括号 {},这样做是一个比较好的习惯:
实例
const x = (x, y) => { return x * y }
this:
首先要知道this的是在代码执行的时候才能确定的,定义的时候不能确定,因为this是执行上下文的一部分,而执行上下文是在代执行的时候才能8定的。实际上this的最终指向的是那个调用它的对象。想理解this先看几个例子:
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的执行会有不同,主要集中在以下几种情况:1.作为构造函数执行,在构造函数中(上面例子未体现)2.作为对象属性执行,上述代码中的a.fn();3.作为普通函数执行,上述代码中fn1();4.用于call,apply,bind,上述代码中a.fn.call({name:'B'});
其中fn1() 的执行结果有些出乎意料,上文说过‘实际上this的最终指向的是那个调用它的对象’,fn1中this为什么指向了window?继续来看例子:
function a() {
var user = "例子";
console.log(this.user);//undefined
console.log(this);//window
}
a();
按照我们上面说的this最终指向的是调用它的对象,这里的函数a实际是被Window对象所点出来的,下面的代码就可以证明:
function a() {
var user = "例子";
console.log(this.user);//undefined
console.log(this);//window
}
window.a();
继续看例子:
var o = {
user: "例子",
fn: function(){
console.log(this.user);//'例子'
console.log(this);// o
}
}
o.fn(); ==>window.o.fn()
o.fn();等价于window.o.fn(),但是this并没有指向window,而是指向O对象;是不是有些迷惑,继续看例子:
var o = {
a = 10;
b : {
a:12;
fn:function(){
console.log(this.a);//12
console.log(this);//b
}
}
}
o.b.fn();
同样属性都是对象o调用出来的,但同样this没有指向O。其实我们需要知道以下几点:
1.如果一个函数中有this,但是没有被上一级对象调用,那么this就指向window,严格模式下t'his将指向undefined;2.如果一个函数中有this,这个函数被上一级对象调用,那么this指向上一级对象;3.如果函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也是其上一级对象。(上面的例子中,将b对象的值注销既可以验证)
var o = {
a = 10;
b : {
//a:12;
fn:function(){
console.log(this.a);//undefined
console.log(this);//b
}
}
}
o.b.fn();
还有个特殊的例子:
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指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,这个例子中虽然函数fn是被对象b所引用,但是在将fn赋值给变量c的时候并没有执行所以最终指向的是window。
在构造函数中this指向也会不同:
function Fn(){
this.user = '例子';
}
var a = new Fn();
console.log(a.user)//'例子'
这里a可以调用到user的值,因为构造函数new关键字改变了this的指向,所以将this指向a。
当this遇到return时结果也会有差异,如下面的连个例子:
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)//'例子'
#####总结: 如果返回值是一个对象,那么this指向返回的这个对象,如果返回值不是一个对象,那么this还是指向函数的实例;null也是一个对象,但是null比较特殊,返回值是null,this还是指向函数的实例。
css实现两栏布局的总结:
两栏布局(左侧宽度固定,右侧自适应),在学习的过程中总结了几种方法:
方法一:float+margin-left
HTML部分
<div class="left">
<h1>Left Side</h1>
<p>我是左侧栏</p>
</div>
<div class="right">
<h1>Right Side</h1>
<p>我是右侧栏</p>
</div>
CSS部分
{
/清除默认格式/
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为左侧元素设置浮动后,左侧元素会因为浮动盖在右侧元素上,因此要将右侧元素变成BFC,BFC是一个独立的区域,不会让BFC外的元素对其内部造成干扰。当右侧元素变成一个BFC时它的元素边界会发生变化,会紧紧贴合左侧的元素。常见的右侧元素设置----overflow:hidden;
方法四:flex布局HTML部分
<div class="box">
<div class="left">
<h1>Left Side</h1>
<p>我是左侧栏</p>
</div>
<div class="right">
<h1>Right Side</h1>
<p>我是右侧栏</p>
</div>
</div>
CSS设置:
{
/清除默认格式/
margin:0;
padding:0;
}
.box{
display:flex;
}
.box1{
}
.box2{
flex:1;
}