函数
1) 作用 -- 函数也是对象,是一个引用数据类型
1. 利用函数可以封装一些具有特殊功能的代码,之后调用即可实现相应的效果
arr.sort(); // 排序
arr.reverse(); // 反转
jQuery();
ajax(); // http请求
2. 利用函数封装对象【api本质/构造函数】高级面向对象
2) 函数创建方式 --函数创建完毕后一般不会自动执行,需要调用
函数声明
function 函数名(形参列表){ // 函数体 } function sayMsg(name,age,gender){ console.log('name:',name); console.log('age:',age); console.log('gender:',gender); } sayMsg('zhangsan',13,'male'); 实参的顺序与形参的顺序是一一对应的 形参可以是对象,访问时obj.属性
函数表达式 -- 匿名函数赋值给变量
var 函数名 = function(形参列表){ // 函数体 }; var fun = function(name,age){ console.log(name); console.log(age); } fun.call(this,'tom',20,'male'); fun.apply(this,['larry',18,'female']);
3) 调用方式
调用时解析器不会检查实参类型,数量
多余的实参不会被赋值,实参不足,没有对应实参的形参是undefined
函数体return后的语句不会执行
return 后无值,无return --- 返回undefined
函数名(实参列表);
函数名.call(this,实参列表);
函数名.apply(this,实参数组);
sayMsg('zhangsan',13,'male');
fun.call(this,'tom',20,'male');
fun.apply(this,['larry',18,'female']);
4) 提升
代码从它们在代码中出现的位置被移动到当前作用域最上方进行执行【解析器操作的】,这个过程叫做提升
变量的提升 -> 用var声明的变量会在所有代码执行前被声明(但是不会被赋值)
1>a = 1; var a; console.log(a); ==>等价于 var a; a = 1; console.log(a); // 1
2>
console.log(a); var a = 1; ==>等价于 var a; console.log(a); // undefined --a未被赋值 a = 1;
函数声明的提升 ->用函数声明方式创建的函数(function a(){}),会在所有代码执行前被创建
1> test(); function test(){ console.log(1); } ==>等价于 function test(){ console.log(1); } test(); // 1 2> fun(); var fun = function(){ //函数表达式创建 console.log(1); } ==>等价于 var fun; fun(); // fun is not a function fun = function(){ console.log(1); }
函数声明与函数表达式的提升 -> 函数声明的提升优先于函数表达式
var fun = function(){ console.log(2); } fun(); function fun(){ console.log(1); } ==>等价于 function fun(){ console.log(1); } var fun = function(){ console.log(2); } fun();
5) 引用数据类型的比较
同一个指针不可以同时指向多个堆内存中的区域
但是同一个堆内存中的区域可以同时被多个指针所指向
var obj1 = {
name:'tom',
age:13,
gender:'male'
}
var obj2 = {
name:'tom',
age:13,
gender:'male'
}
var obj3 = obj1;
console.log(obj1 == obj2); // false
console.log(obj1 === obj2); // false
console.log(obj1 == obj3); // true
console.log(obj1 === obj3); // true
6) 函数的内部属性 -> 只有在函数内部可以访问到的属性
- 形参
接收参数的快捷方式 arguments【类数组对象】
当前函数接受的所有参数所存储的地方{ '0': 'tom', '1': '13', '2': 'male', length:3 // 只有在浏览器打印时才显示 } callee 指向当前的函数 将类数组对象转换为数组
*3. this
当前函数执行时所依赖的环境
nodejs -> global对象
浏览器 -> window对象
this的指向性问题
可以根据函数的调用方式来判断
函数名(实参列表);
函数名.call(this,实参列表);
函数名.apply(this,实参数组);
1、以()方式调用函数
如果函数名的左边没有对象,则this指向全局
function test(){
console.log(this);
}
test(); //函数方式调用
nodejs -> global对象
浏览器 -> window对象 =window.test()
如果函数名的左边有对象,则this指向该对象
var obj1 = {
name:'tom',
sayName:function(){
console.log(this.name);
}
}
var obj2 = {
name:'terry',
sayName:function(){
console.log(this.name);
}
}
//以方法方式调用
obj1.sayName(); // this指向了obj1对象 tom
obj2.sayName(); // this指向了obj2对象 terry
2、以call和apply的方式调用
更改this的指向
var obj1 = {
money:'有钱',
pay:function(){
console.log(this.money);
}
}
var obj2 = {
money:'没钱'
}
obj1.pay(); // 有钱
obj1.pay.call(obj2); // 通过call()将this指向obj2 没钱
obj1.pay.apply(obj2); // 通过apply()将this指向obj2 没钱
3、箭头函数的this指向外部函数的this
function(){} es5
()=>{} es6
7) 闭包
函数内部的函数
function test(){
function a(){
}
}
function test(){
var name = 'tom';
function a(){
return name;
}
return a();
}
var res = test();
console.log(res); // tom
function test(){
var name = 'tom';
console.log(age,'-----'); //age--undefined
function a(){
var age = 13;
return name;
}
return a();
}
var res = test();
console.log(res);
内部函数可以访问外部函数中的属性,但是外部函数不能访问内部函数的属性
8) 匿名函数和自执行函数
匿名函数:没有名字的函数
function(){}
自执行函数:会自动执行的函数---只执行一次
( function(){} ) ()
函数对象
(function(){
console.log(1);
})(); // 1
(function(name,age){
console.log(name);
console.log(age);
})('zhangsan',13); // zhangsan 13
9) 方法
函数作为对象的属性,将该函数叫做对象的方法
var obj = new Object();
obj.name="jerry";
obj.sayName = function(){ //方法
console.log(obj.name);
};
obj.sayName(); //调用对象的方法
10)作用域
1.全局作用域
- 页面打开时创建,页面关闭时销毁
- 有一个全局对象window--代表浏览器窗口,由浏览器创建,可以直接使用
- 全局中创建的变量都会作为window对象的属性保存
全局中创建的函数都会作为window对象的方法保存
- 域中变量都为全局变量,页面任意部分均可访问
var a=1;
console.log(window.a);
function fun(){}
window.fun();
2.函数作用域
-调用函数时创建,函数执行结束则销毁
-每调用一次函数就会创建一个新的作用域
-函数作用域中可以访问全局变量
-在函数作用域中创建变量,会先在自身作用域寻找,无则在上一级作用域寻找,直到全局作用域,若依旧无,则会报错ReferenceError
-函数作用域中想访问全局变量 -- window.a
-有变量提升 -- var声明变量会提前, 有函数提升
-函数内变量未用var 声明,则是全局变量
-定义形参相当于在函数作用域中声明了变量
eg:
1>
var a = 10;
function fun(){
var a = 20;
function func2(){
console.log(a); //a = 20
console.log(window.a) //a = 10
}
fun2();
}
fun();
2>
var c =10;
function fun(){
console.log(c);
c=20;
d=100;
}
fun(); //c=10 --找全局
console.log(c); //c=20 --函数内c未用var 声明,是全局变量
console.log(d); //d = 100 -- 可访问,因为d是全局
3>
var e = 10;
function fun(e){
//var e; 定义形参即声明变量
console.log(e);
}
fun(); //underfined
1、构造函数和普通函数的区别
1) 首字母
2) 调用方式
构造函数通过new关键字调用
var obj = new Object();
new Vue();
普通函数直接调用
function sayName(){
xxx
}
sayName();
2、函数使用()和不使用()的区别
使用(),表示调用当前函数,并返回函数的返回值
不使用(),表示一个指向当前函数的指针
如何将一个函数赋值给一个变量,再将变量放入到对象中?
错误代码:
function test(){
console.log(1);
return 'hello world';
}
var a = test();
var obj = {
name:a
}
console.log(obj); // 1 {name:'hello world'}
正确代码:
function test(){
console.log(1);
return 'hello world';
}
var a = test;
var obj = {
name:a
}
console.log(obj); // {name:[Function: test]}
3、return与console.log()的区别
函数使用return之后才会有返回值
函数使用console.log是没有返回值的
function test(){
console.log(1);
}
function fun(){
return 2;
}
var a = test();
var b = fun();
console.log(a); // 1 undefined
console.log(b); // 2