JavaScript学习记录03函数的定义、变量的作用域、方法
3.1函数的定义
JavaScript 函数是被设计为执行特定任务的代码块。
JavaScript 函数会在某代码调用它时被执行。
function myFunction(p1, p2) {
return p1 * p2; // 该函数返回 p1 和 p2 的乘积
}
JavaScript 函数通过 function 关键词进行定义,其后是函数名和括号 ()。
函数名可包含字母、数字、下划线和美元符号(规则与变量名相同)。
圆括号可包括由逗号分隔的参数:
(参数 1, 参数 2, ...)
由函数执行的代码被放置在花括号中:{}
function name(参数 1, 参数 2, 参数 3) {
要执行的代码
}
如,定义方式一:
function abs(x){
if (x>=0){
return x;
}else {
return -x;
}
}
定义方式二:
var abs = function(x){
if (x>=0){
return x;
}else {
return -x;
}
}
效果一样
一旦执行到return代表函数结束,返回结果
如果没有执行ruturn,函数执行完也会返回结果,结果为undefined
参数问题:
JavaScript可以传任意个参数,也可以不传递参数
传递参数需要通过手动抛出异常来判断是否有问题:
function abs(x) {
if (typeof x != 'number') {
throw 'Not a number';
}
if (x >= 0) {
return x;
} else {
return -x;
}
}
2、arguments
arguments是JS免费赠送的关键字;
function abs(x) {
console.log("x=>" + x);
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
if (x >= 0) {
return x;
} else {
return -x;
}
}
arguments可以遍历所有的参数
代表传递进来的多有参数是一个数组。
问题:arguments包含所有的参数,若想使用多余的参数来进行附加操作,需要排除已有参数
3、rest
获取除了已经定义的参数之外的所有参数
function aaa(a, b) {
console.log("a=>" + a);
console.log("b=>" + b);
if (arguments.length > 2) {
for (var i = 2; i < arguments.length; i++) {
//...
}
}
}
改善后:
function aaa(a, b,...rest) {
console.log("a=>" + a);
console.log("b=>" + b);
console.log(rest);
}
无论输入多少个,只把第二个放入b中
rest参数,只能写在最后面,必须用…标识
3.2变量的作用域
在js中,变量的定义并不是以代码块作为作用域的,而是以函数作为作用域。也就是说,如果变量是在某个函数中定义的,那么,它在函数以外的地方是不可见的。但是,如果该变量是定义在if或者for这样的代码块中,它在代码块之外是可见的。
在 JavaScript 中有两种作用域类型:
- 局部作用域
- 全局作用域
JavaScript 拥有函数作用域:每个函数创建一个新的作用域。
作用域决定了这些变量的可访问性(可见性)。
函数内部定义的变量从函数外部是不可访问的(不可见的)。(类似Java的内部类)
例:
1、假设在函数体中声明,则在函数体外不可以使用
function qj(){
var x = 1;
x = x + 1;
}
x = x + 2;//x is not defined
2、如果两个函数使用相同的变量名,只要在函数内部就不会冲突
function qj(){
var x = 1;
x = x + 1;
}
function qj2(){
var x = 'a';
x = x + 1;
}
3、内部函数可以访问外部函数的成员,反之不行
function qj(){
var x = 1;
function qj2(){
var y = x + 1; //2
}
var z = y + 1; //y is not defined
}
4、内部函数变量和外部函数变量重名
function qj() {
var x = 1;
function qj2() {
var x = 'a';
console.log('inner' + x);
}
console.log('outer' + x);
qj2()
}
qj()
在JavaScript中函数查找变量从自身函数开始,由“内”向“外”查找,若外部存在这个同名的函数变量,则内部函数会屏蔽外部函数的变量。
5、提升变量的作用域
function qj() {
var x = "x" + y;
console.log(x);
var y = 'y';
}
qj()
说明js执行引擎自动提升了y的声明,但是不会提升变量y的赋值。
养成规范:所有变量定义都放在函数的头部,便于代码维护。
6、全局变量
var x = 1; //全局变量
function f() {
console.log(x);
}
f();
console.log(x);
7、全局对象window
var x = 'xxx';
alert(x);
alert(window.x);//默认所有的全局变量,都会自动绑定在window对象下;
JavaScript实际上只有一个全局作用域,任何变量(函数也可视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,就会报错
规范
由于我们所有的全局变量都会绑定到window上,如果不同的js文件使用了相同的全局变量,就会产生冲突,如何减少冲突?
//唯一全局变量
var kuangapp = {};
//定义全局变量
kuangapp.name = 'kuang';
kuangapp.add = function (a,b){
return a + b;
}
把自己的代码全部放入自己定义的唯一空间名字中,减少全局命名的冲突问题。
8、局部作用域let
引例:
function aaa() {
for (var i = 0; i < 100; i++) {
console.log(i);
}
console.log(i + 1);
}
这段代码中,console.log(i + 1);
的i出了作用域还可以使用,为了解决这个问题,ES6提出let关键字。
function aaa() {
for (let i = 0; i < 100; i++) {
console.log(i);
}
console.log(i + 1);
}
9、常量const
在ES6之前定义常量,只有用全部大写字母命名的变量就是常量
var PI = '3.14';
console.log(PI);
PI = '222'; //可以改变PI的值
console.log(PI);
ES6引入了常量关键字const:
const PI = '3.14';
console.log(PI);
PI = '222';
console.log(PI);
报错:
3.3方法
方法就是把函数放在对象里面,对象只有两个东西:属性和方法
var kuang = {
name:'zhangsan',
birth:2020,
//方法
age:function (){
var now = new Date().getFullYear();
return now - this.birth;
}
}
调用方法一定要带括号“()”
把上面的代码拆开:
function getAge() {
var now = new Date().getFullYear();
return now - this.birth;
}
var kuang = {
name: 'zhangsan',
birth: 2020,
//方法
age: getAge
}
效果一样。
但如果之间调用getAge()方法就不行
this是无法指向的,默认指向调用它的对象。
解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象,根据函数的调用方式的不同,this会指向不同的对象:
1、以函数的形式调用时,this永远是window
2、以方法的形式调用时,this就是调用方法的对象
3、当以构造函数的形式调用时,this就是新创建的那个对象
function fun() {
console.log(this);
}
var obj = {
name: "孙悟空",
sayName: fun
};
obj.sayName();//this是obj
fun();//this是window
apply
在js中可以控制this指向
function getAge() {
var now = new Date().getFullYear();
return now - this.birth;
}
var kuang = {
name: 'zhangsan',
birth: 2020,
//方法
age: getAge
};
getAge.apply(kuang,[]); //this指向kuang这个对象,参数为空
this可以根据调用者的不同变成不同的值:
var name = "全局";
function fun() {
console.log(this.name);
}
var obj = {
name: "孙悟空",
sayName: fun
};
var obj2 = {
name:"沙和尚",
sayName: fun
}
obj.sayName();//孙悟空
obj2.sayName();//沙和尚
感觉狂神的JS课逻辑有点乱…