JavaScript学习笔记
1. 入门知识
1.1 编写位置
- 标签的指定属性:
<button onclick="alert('hello');">我是按钮</button>
<a href="javascript:alert('aaa');">超链接</a>
注: 在给一个超链接或者按钮设置无跳转操作的时候可以如下编写:
<a href="javascript:;">超链接</a>
- html内的script标签中
<script type="text/javascript">
//编写js代码
</script>
- 外部js文件
<script type="text/javascript" src="文件路径"></script>
注: script标签一旦用于引入外部文件,就可以再编写代码了。
1.2 注释
- 单行注释
// 单行注释
- 多行注释
/*
多行注释
*/
1.3 字面量和变量
- 字面量
字面量实际上就是一些固定的值,比如 1 2 3 4 true false null NaN “hello”
字面量都是不可以改变的 - 变量
变量可以用来保存任意的字面量。
(1)声明变量
使用var关键字来声明一个变量
var a;
(2)为变量赋值
a = 1;
(3)声明和赋值同时进行
var a = 123;
1.4 标志符
- 在JS中所有的可以自主命名的内容,都可以认为是一个标识符。
- 比如:变量名、函数名、属性名。
- 标志符规范如下:
(1)标识符中可以含有字母、数字、_、$
(2)标识符不能以数字开头
(3)标识符不能是JS中的关键字和保留字
(4)标识符一般采用驼峰命名法:首字母小写,每个单词的开头字母大写,其余字母小写。例:appleSunTree
2. 数据类型(5+1)
六种数据类型 = 5个基本数据类型+object
- String 字符串(基本数据类型)
- Number 数值(基本数据类型)
- Boolean 布尔值(基本数据类型)
- Null 空值(基本数据类型)
- Undefined 未定义(基本数据类型)
- Object 对象(引用数据类型)
typeof运算符可以检查数据类型
2.1 string 字符串
JS中的字符串需要使用双引号或单引号引起来。
注: 同种引号不能嵌套使用,异种引号可以。
var str = "hello";
2.2 number 数值
- JS中所有的数值都是Number类型,包括整数和浮点数。
- JS中能表示的最大值:Number.MAX_VALUE = 1.7976931348623157e+308。如果一个数字的数值超过这个最大值则返回Infinity。
例:
console.log(Number.MAX_VALUE*Number.MAX_VALUE)
- Infinity 正无穷 a = Infinity ,能赋值。使用typeof检查Infinity 也会返回Number。
- -Infinity 负无穷。
- NaN 表示Not A Number。使用typeof检查NaN 也会返回Number。
输出: - 最小正数Number.MIN_VALUE = 5e-324
- Js运算整数可以保证精确,但是运算浮点数可能会不精确,所以千万不要用JS进行精确度要求比较高的运算。
2.3 boolean 布尔值
- 布尔值主要用来进行逻辑判断,布尔值只有两个
- true 逻辑的真
- false 逻辑的假
- 使用typeof检查一个布尔值时,会返回”boolean”
2.4 null 空值
- Null类型的值只有一个:null
- null专门用来表示为空的对象
- 使用typeof检查一个Null类型的值时会返回object
2.5 undefined 未定义
- Undefined类型的值只有一个: undefined
- 声明一个变量但是没有为变量赋值此时变量的值就是undefined
- 使用typeof检查一个Undefined类型的值时,会返回”undefined”
2.6 引用数据类型(object 对象)
- 对象是JS中的引用数据类型
- 对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性
- 使用typeof检查一个对象时,会返回object (检查null也返回object)
2.6.1 对象的分类
1. 内建对象
- 由ES标准中定义的对象,在任何的ES的实现中都可以使用
- 比如:Math String Number Boolean Function Object….
2. 宿主对象
- 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
- 比如 BOM DOM
3.自定义对象
- 由开发人员自己创建的对象
2.6.2 对象的创建
- 方法一:
注意: 使用new关键字调用的函数,是构造函数constructor。构造函数是用来专门创建对象的函数。
var obj = new Object();
- 方法二:
- 使用对象字面量,可以在创建对象时,直接指定对象中的属性。
- 语法:{属性名:属性值,属性名:属性值}
- 对象字面量的属性名可以加引号也可以不加引号,建议不加。
- 属性名和属性值是一组一组的名值对结构。
var obj = {};
var obj2 = {
name:"张三",
age:25,
gender:"男"
}
- 方法三:
- 使用工厂方法创建对象。通过该方法可以大批量创建对象。
function createPerson(name,age,gender){
// 创建一个新的对象
var obj = new Object();
// 向对象中添加属性
obj.name = name;
obj.age = age;
obj,gender = gender;
obj,sayName =function(){
console.log(this.name);
};
// 将新的对象返回
return obj;
}
var obj = createPerson("张三",18,"男”);
- 使用工厂方法创建的对象,使用的构造函数都是Object,所以创建的对象都是Object这个类型,就导致我们无法区分多钟不同类型的对象。
- 方法四:
- 构造函数是专门用来创建对象的函数。
- 构造函数习惯上首字母大写。
- 一个构造函数我们也可以称为一个类。
- 通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例。
- 通过同一个构造函数创建的对象,我们称为一类对象。
- 构造函数就是一个普通的函数,只是他的调用方式不同:
(1)如果直接调用,它就是一个普通函数
(2)如果使用new来调用,则它就是一个构造函数。
function Person(name , age , gender){
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function(){
alert(this.name);
};
}
var p1 = Person("张三",18,"男");
console.log(p1);//undefined
var p2 = new Person("张三",18,"男");
console.log(p2);//object Person {name: "张三", age: 18, gender: "男", sayName: ƒ}
- 构造函数的执行流程:
(1)创建一个新的对象
(2)将新的对象作为函数的上下文对象(this)
(3)执行函数中的代码
(4)将新建的对象返回 - instanceof 用来检查一个对象是否是一个类的实例
- 语法:对象 instanceof 构造函数
console.log(p1 instanceof Person); // true
- 如果该对象时构造函数的实例,则返回true,否则返回false
- Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true
console.log(p1 instanceof Object); // true
2.6.3 添加对象的属性
- 对象的属性值可以是任何的数据类型,也可以是函数。
- 如果一个函数作为一个对象的属性保存,那么我们称这个函数为对象的方法。
- 调用函数就说是调用对象的方法。
- 但是这个只是名称上的区别,本质没有差别。
var obj = {name :'张三',age : 18}
obj.sayName = function(){
console.log(obj.name);
};
obj.sayName();
- 语法:
对象.属性名 = 属性值;
对象[“属性名”] = 属性值; //这种方式能够使用特殊的属性名
- 对象的属性名没有任何要求,不需要遵守标识符的规范,但是在开发中,尽量按照标识符的要求去写。
- 如果使用特殊的属性名,不能采用.的方式来操作,需要使用另一种方式:
语法:对象[“属性名"]
obj["123eqdassfds ada "] = 123;
- 使用**[]这种形式去操作属性,更加灵活**。[]中可以传变量,变量值是多少,对象的该属性值就是多少。
var obj = new Object();
var n = 123;
console.log(obj[n]); // 123
- 属性值也可以任意的数据类型,甚至也可以是一个对象。
var obj = new Object();
// 向obj中添加一个name属性
obj.name = "孙悟空";
// 向obj中添加一个gender属性
obj.gender = "男";
// 向obj中添加一个age属性
obj.age = 18;
2.6.4 读取对象的属性
- 语法:
对象.属性名
对象[“属性名”] //“属性名”可以使字符串常量,也可以是字符串变量
- 如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined
var obj = new Object();
// 向obj中添加一个name属性
obj.name = "孙悟空";
// 向obj中添加一个gender属性
obj.gender = "男";
// 向obj中添加一个age属性
obj.age = 18;
console.log(obj.name)
2.6.5 修改对象的属性
- 语法:
对象.属性名 = 新值
var obj = new Object();
// 向obj中添加一个name属性
obj.name = "孙悟空";
obj.name = "Tom";
console.log(obj.name)
2.6.6 删除对象中的属性
- 语法:
delete 对象.属性名
delete 对象["属性名"]
var obj = new Object();
// 向obj中添加一个name属性
obj.name = "孙悟空";
delete obj.name;
console.log(obj.name); // undefined
2.6.7 判断对象中是否有该属性
- 使用in检查对象中是否含有指定属性
- 语法:
”属性名” in 对象
- 如果在对象中含有该属性,则返回true
- 如果没有则返回false
var obj = new Object();
obj.test = "123";
console.log("test" in obj);// true
console.log("name" in obj);// fasle
2.6.8 枚举对象中的属性(遍历)
- 遍历对象
- 使用for … in 语句.
- 语法:
for (var 变量 in 对象){
} // 对象中有几个属性就循环几次;每次执行,会把对象中的一个属性名字赋值给变量。
var obj = {
name : "张三",
age : 18,
height:"1.88"
}
for(var v in obj){
document.write("property:name ="+v+"value="+obj[v]+"<br/>" );
}
2.7 基本数据类型和引用数据类型的区别
- 基本数据类型的数据,在栈内存储,变量是直接保存的它的值。
- 变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
var a = 123;
var b = a;
a++;
console.log(a); // 124
console.log(b); // 123
- 引用数据类型的数据,在堆内存储,变量是保存的对象的引用(内存地址)。每创建一个新的兑现,就会在堆内存中开辟出一个新的内存地址。
- 如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
- 比较两个变量时,对于基本数据类型,比较的就是值,
- 对于引用数据类型比较的是地址,地址相同才相同。
var obj = new Object();
obj.name = "张三";
var obj2 = obj;
obj.name = "李四";
console.log(obj.name); // "李四"
console.log(obj2.name); // "李四"
2.7 强制类型转换
- 指的是将一种数据类型转换为其他的数据类型。
- 主要是指其他类型转换为String Number 或 Boolean
1. 转换为String
(1)toString() (强制类型转换)
调用被转换数据的toString()方法,该方法不会影响原变量,它会返回转换的结果。
var a = 123;
a = a.toString();
var b = true;
b = b.toString();
**注:**这个方法不适用于null和undefined,这两个类型的数据中没有方法,所以调用toString()时会报错。
(2)调用String()函数 (强制类型转换)
调用String()函数,并将被转换的数据作为参数传递。
var a = 123;
a = String(a);
对于Number Boolean String都会调用他们的toString()方法来将其转换为字符串,对于null值,直接转换为字符串”null”。对于undefined直接转换为字符串”undefined”
(3)为任意的数据类型 +”” (隐式的类型转换)
var a = true;
a = a + "";
2. 转换为Number
(1)Number() (强制类型转换)
var s = "123";
s = Number(s);
转换的情况:
- 字符串 -> 数字
如果字符串是纯数字的内容,则直接转换为对应的数字
如果字符串是有非数字的内容,则转换为NaN
如果是一个空串或纯空格的字符串,则转换为0 - 布尔值 -> 数字
true转换为1
false转换为0 - 空值 -> 数字
null转换为0 - 未定义 > 数字
undefined 转换为NaN
(2)parseInt()或parseFloat() (强制类型转换)
- 如果对非String使用parseInt()或parseFloat(),它会先将其转换为String然后在操作 parseInt()。
- 可以将一个字符串中的有效的数字位提取出来,并转换为Number。
例:
var a = "123.456px";
var b = parseInt(a); //123
var c = parseFloat(a); //123.456
3. 转换为boolean
(1) 数字转boolean 除了0和NaN都是true
var a = 123;
var b = -465;
var c = 0;
var d = Infinity;
var e = NaN;
console.log(Boolean(a)); // true
console.log(Boolean(b)); // true
console.log(Boolean(c)); // false
console.log(Boolean(d)); // true
console.log(Boolean(e)); // false
(2)字符串转boolean 除了空串都是true
var a = “123”;
var b = “”;
console.log(Boolean(a)); // true
console.log(Boolean(b)); // false
(3)null和undefined转boolean 都是false
(4)对象转boolean 都是true
2.8 数字进制转换
- JS中十六进制数字以0x开头
var a = 0x10
console.log(a); // 16
var b = 0xff
console.log(b); // 255
- JS中八进制数字以0开头
var a = 070
console.log(a); // 56
- JS中二进制数字以0b开头(不是所有浏览器都支持)
var a = 0b10;
console.log(a); // 2
- 使用parseInt(字符串变量名名,进制)可以将字符串转换成不同进制。
var a = "070";
console.log(parseInt(a,10); //70
console.log(parseInt(a,8); //56
3. 基础语法
3.1 算术运算符
运算符也称为操作符,通过运算符可以对一个或多个值进行运算或操作。
" - * \ %",对非Number类型的值进行运算时,都会先转换为Number然后在做运算。
3.1.1 简介
- +
- 可以对两个值进行加法运算,并将结果返回。
- 当对非Number类型的数值进行运算时,会将这些值转换为Number然后再运算。
- 任何值和NaN做运算都等于NaN。
- 对两个字符串进行加法操作,会进行拼串操作。
- 任何值和字符串做加法都会先转换为字符串再进行拼串。(可以利用这一特点进行隐式转换:把其他类型的变量转换为字符串类型,实际上也是调用了String函数)
var res = true + false; // 1+0=1
res = true + 1; // 1+1 = 2
res = 2 + null l; 2+0 =2
res = 2 + NaN ; // NaN
res = "123" + "456"; // "123456" 拼串
res = 1 + "123"; // "1123"
res = true + "hello" ; // "truehello" 拼串
res = null + "" ; // "null"
- -
- 可以对两个值进行减法运算,并将结果进行返回。
var res = 100 -95; // 5
res = 100 - true ; // 100-1 = 99
res = 100 - "1" ; // 99
- *乘法
- 可以对两个值进行乘法运算,并将结果进行返回。
var res = 2 * 2; // 4
res = 2 * "8" ; // 2*8 = 16
res = 2 * undefined ; // 2 * NaN = NaN 任何数和NaN运算都是NaN
res = 2 * null ; //2 * 0 = 0
- /
- 可以对两个值进行除法运算,并将结果进行返回。
- %
- 可以对两个值进行取模运算,并将结果进行返回。
3.1.2 一元运算符
一元运算符只需要一个操作数。
- +
正号,不会对值产生任何影响,但是可以将一个非数字隐式转换为数字。
var a = true;
a = a + '123' // true123
a = "18";
a = +a ; // 18 隐式转换为数字
var res = 1 + +"2" + 3; // 6
- -
就是负号,可以对一个数字进行符号位取反。也可以对布尔值进行隐式转换为字符串。
var a = true;
a = -a // -1
a = "123"
a = -a ; -123
3.1.3 自增运算符
自增可以使变量在原值的基础上自增1
- ++a的值是变量的新值(自增后的值)
- a++的值是变量的原值(自增前的值)
var d = 20;
var res = d++ + ++d + d ; // 20 + 22 + 22
3.1.4 自减运算法
自减可以使变量在原值的基础上自减1
- –a的值是变量的新值(自减后的值)
- a–的值是变量的原值(自减前的值)
3.2 逻辑运算符
3.2.1 非 !
- 非运算可以对一个布尔值进行取反,true变false false变true
- 当对非布尔值使用!时,会先将其转换为布尔值然后再取反
- 我们可以利用!来将其他的数据类型转换为布尔值
- 对一个布尔值两次取反,这个值没有变化。
- 隐式转换:对一个任意类型的数值进行两次取反,将其转换为布尔值。原理和Boolean()函数一样。
3.2.2 与&&
- &&可以对符号两侧的值进行与运算
- 只有两端的值都为true时,才会返回true。只要有一个false就会返回false。
- 与是一个短路的与,如果第一个值是false,则不再检查第二个值
- 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
- 规则:
- 1.如果第一个值为false,则返回第一个值
2.如果第一个值为true,则返回第二个值
(1) 如果两个值都为true,则返回后面的
javascript var result = 5 && 6; // 6
(2) 如果某一个值为false,则返回0
var result = 0 && 7; // 0
result = 7 && 0; // 0
(3) 如果两个都是false,则返回前面的
var result = NaN && 0; // NaN
result = 0 && NaN ; // 0
3.2.3 或||
- ||可以对符号两侧的值进行或运算
- 只有两端都是false时,才会返回false。只要有一个true,就会返回true。
-或是一个短路的或,如果第一个值是true,则不再检查第二个值 - 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
- 规则:
1.如果第一个值为true,则返回第一个值
var res = 2 || 1; //2
res = 2 || NaN; //2
res = 2 || 0; //2
2.如果第一个值为false,则返回第二个值
var res = NaN || 1; //1
res = NaN ||0; //0
res = "" || "hello"; //"hello"
res = -1 || 0; // -1
3.3 赋值运算符
- = 可以将符号右侧的值赋值给左侧变量
- +=
- -=
- %=
- *=
- /=
3.4 关系运算符
- 关系运算符用来比较两个值之间的大小关系的。
- 如果关系成立会返回true,如果关系不成立返回false
- 大于、小于、大于等于、小于等于、==
- 大于小于
- 如果比较的两个值是非数值,会将其转换为Number然后再比较。
console.log(1>true) ; // false
console.log(1>=true) ;// true
console.log(1>='0') ;// true
console.log(10>null) ;// true
console.log(true>false) ;// 1 > 0 true
- 任何值和NaN作比较都是fasle
console.log(10>"hello") ;// 10>undefined false
- 如果比较的两个值都是字符串,此时不会转换为Number,而是会比较字符串的Unicode编码。
console.log("1">"5") ;// false
console.log("11">"5") ;// false
console.log("a"<"b") ;// 97 < 98 true
- 比较字符编码时,是一位一位比较。如果两位一样,则比较下一位,所以借用它来对英文进行排序。比较中文没有意义。
console.log("abc"<"b") ;// 97 < 98 true
console.log("bbc"<"b") ;// 99 < 98 false
- 如果比较的两个字符串型的数字,可能会得到不可预期的结果。注意:比较的两个字符串型的数字一定要转型。
- 相等
- 相等,判断左右两个值是否相等,如果相等返回true,如果不等返回false
- 相等会自动对两个值进行类型转换,如果对不同的类型进行比较,会将其转换为相同的类型然后再比较,转换后相等它也会返回true。
console.log("1"==1); // 1==1 true
console.log("true"==1); // "true"==1 false
console.log(1=="hello"); // false
console.log(null==0); // false
- undifined衍生自null,因此 null == undifined
console.log(null==undifined); // true
- NaN不和任何值相等,包括它本身。
console.log(NaN==NaN); // false
- 判断某个值是否为NaN,可以通过isNaN()函数来判断。
var a = NaN;
console.log(isNaN(a));// true
- 不相等
- 不等,判断左右两个值是否不等,如果不等则返回true,如果相等则返回false。
- 不等也会做自动的类型转换。
- 全等
- 判断左右两个值是否全等,它和相等类似,只不过它不会进行自动的类型转换,
- 如果两个值的类型不同,则直接返回false
console.log("123"==123); // true
console.log("123"===123); // false
console.log(null==undifined); // true
console.log(null===undifined); // false
- 不全等
- 和不等类似,但是它不会进行自动的类型转换。
- 如果两个值的类型不同,它会直接返回true。
console.log("123"!=123); // false
console.log("123"!==123); // true
3.5 条件运算符?:
- 条件运算符也叫三元运算符
- 语法:条件表达式?语句1:语句2;
- 执行流程:
(1)先对条件表达式求值判断,
(2)如果判断结果为true,则执行语句1,并返回执行结果
(3)如果判断结果为false,则执行语句2,并返回执行结果
true?alert(1):alert(2); // 1
false?alert(1):alert(2); // 2
var a = 10;
var b = 20;
a > b ? alert("a大"):alert("b大"); // a大
// 获取a和b中的最大值
var max = a > b ? a:b;
// 获取a b c中的最大值
max = max > c?max:c;
3.6 运算符的优先级
- 和数学中一样,JS中的运算符也是具有优先级的,比如 先乘除 后加减 先与 后或
- 具体的优先级可以参考优先级的表格,在表格中越靠上的优先级越高,
- 优先级越高的越优先计算,优先级相同的,从左往右计算。
- 优先级不需要记忆,如果遇到拿不准的,使用()来改变优先级。
3.6 Unicode编码
- 在js中使用转义字符输入Unicode编码
\u四位编码
console.log("\u2620"); // 16进制
- 在网页中使用Unicode编码
&#编码;
<h1>☠</h1> // 10进制
3.7 语句
- 程序都是自上向下的顺序执行的,
3.7.1 代码快
- 一个{}中的语句称之为一个代码块。
- 在代码块后面不用再写分号;
- Js的代码块只有分组的作用,没有其他用途。
- 代码块中的内容在外部是完全可见的。
{
var a = 10;
console.log("hello");
}
console.log(a); // 10
3.7.2 流程控制语句
- 通过流程控制语句可以改变程序执行的顺序,或者反复的执行某一段的程序。
- 条件判断语句
- 条件判断语句也称为if语句
- 语法一:
if(条件表达式){
语句...
}
- 执行流程:
(1) if语句执行时,会先对条件表达式进行求值判断,
(2) 如果值为true,则执行if后的语句
(3) 如果值为false,则不执行if后的语句 - 语法二:
if(条件表达式){
语句...
}else{
语句...
}
- 执行流程:
(1)if…else语句执行时,会对条件表达式进行求值判断,
(2)如果值为true,则执行if后的语句
(3) 如果值为false,则执行else后的语句
- 语法三:
if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else{
语句...
}
- 执行流程
(1) if…else if…else语句执行时,会自上至下依次对条件表达式进行求值判断,
(2) 如果判断结果为true,则执行当前if后的语句,执行完成后语句结束。
(3) 如果判断结果为false,则继续向下判断,直到找到为true的为止。
(4) 如果所有的条件表达式都是false,则执行else后的语句
- 条件分支语句
- switch语句
- 语法:
switch(条件表达式){
case 表达式:
语句...
break;
case 表达式:
语句...
break;
case 表达式:
语句...
break;
default:
语句...
break;
}
- 执行流程:
(1) switch…case…语句在执行时,会依次将case后的表达式的值和switch后的表达式的值进行全等比较,
(2) 如果比较结果为false,则继续向下比较。如果比较结果为true,则从当前case处开始向下执行代码。
(3) 如果所有的case判断结果都为false,则从default处开始执行代码。
var num = 2;
switch(num){
case 1:
console.log(1);
break;
case 2:
console.log(2);
break;
case 3:
console.log(3);
break;
default:
console.log(2333);
break;
}
- 循环语句
通过循环语句可以反复执行某些语句多次
(1) while循环
- 语法:
while(条件表达式){
语句...
}
- 执行流程:
(1)while语句在执行时,会先对条件表达式进行求值判断,
(2)如果判断结果为false,则终止循环。
(1)如果判断结果为true,则执行循环体。
(4)循环体执行完毕,继续对条件表达式进行求值判断,依此类推。
(2)do…while循环
- 语法:
do{
语句...
}while(条件表达式)
- 执行流程
(1)do…while在执行时,会先执行do后的循环体,然后在对条件表达式进行判断,
(2)如果判断判断结果为false,则终止循环。
(3)如果判断结果为true,则继续执行循环体,依此类推 - 和while的区别:
(1)while:先判断后执行
(2)do…while: 先执行后判断
(3)do…while可以确保循环体至少执行一次。
(3)for循环
-语法:
for(初始化表达式 ; 条件表达式 ; 更新表达式){
语句...
}
- 执行流程:
(1) 首先执行初始化表达式,初始化一个变量,
(2) 然后对条件表达式进行求值判断,如果为false则终止循环
(3) 如果判断结果为true,则执行循环体
(4) 循环体执行完毕,执行更新表达式,对变量进行更新。
(5) 更新表达式执行完毕重复
4. 函数
- 函数也是一个对象,也具有普通对象的功能(能有属性)。
- 函数中可以封装一些功能代码,在需要的时候可以去调用函数来执行这些代码。
- 使用typeof检查一个函数对象时会返回function。
4.1 创建
(1)函数声明:
function 函数名([形参1,形参2...形参N]){
语句...
}
(2)函数表达式:
var 函数名 = function([形参1,形参2...形参N]){
语句...
};
4.2 参数
参数,函数的实参也可以是任意的数据类型。
- 形参:形式参数
- 定义函数时,可以在()中定义一个或多个形参,形参之间使用**,**隔开。
- 定义形参就相当于在函数内声明了对应的变量但是并不赋值.
- 形参会在调用时才赋值。
function sum(a,b){
console.log(a+b);
}
- 实参:实际参数
- 调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参。
function sum(a,b){
console.log(a+b);
}
sum(1,2); //实参
- 调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值。
- 解析器不会检查实参的数量:
- 如果实参的数量大于形参,多余实参将不会赋值,
- 如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined
- 实参可以是一个对象,也可以是一个函数,
4.3 返回值
- 返回值,就是函数执行的结果。
- 使用return 来设置函数的返回值。
- 语法:
return 值;
- 该值就会成为函数的返回值,可以通过一个变量来接收返回值
- return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出。
- return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。
- 如果return后不跟值,或者是不写return则函数默认返回undefined。
4.4 立即执行函数
- 函数定义完,立即被调用,这种函数叫做立即执行函数
- 立即执行函数往往只会执行一次
(function(a,b){
console.log("a = "+a);
console.log("b = "+b);
})(123,456);
4.5 作用域
作用域指一个变量的作用范围。
4.5.1 全局作用域
- 直接在script标签中编写的代码都运行在全局作用域中
- 全局作用域在打开页面时创建,在页面关闭时销毁。
- 全局作用域中有一个全局对象window,window对象由浏览器提供,
- 可以在页面中直接使用,它代表的是整个的浏览器的窗口。
- 在全局作用域中创建的变量都会作为window对象的属性保存
- 在全局作用域中创建的函数都会作为window对象的方法保存
- 在全局作用域中创建的变量和函数可以在页面的任意位置访问。
- 在函数作用域中也可以访问到全局作用域的变量。
- 尽量不要在全局中创建变量。
var a = 10;
console.log(window.a); // 10
4.5.2 函数作用域
- 函数作用域是函数执行时创建的作用域。
- 每次调用函数都会创建一个新的函数作用域,它们之间是互相独立的。
- 函数作用域在函数执行时创建,在函数执行结束时销毁。
- 在函数作用域中可以访问到全局的作用域的变量。
var a = 10;
function fun(){
console.log(a); // 10
}
- 在函数作用域中创建的变量,不能在全局中访问。
function fun(){
var a = 10;
}
console.log(a); // error: a is not defined
- 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找。
var a = 10;
function fun(){
var a = 233;
console.log(a); // 233
}
- 如果找到了则直接使用,如果没有找到则到上一级作用域中寻找。(类似套娃)
- 如果找到了则使用,找不到则继续向上找,直到找到全局作用域。如果全局作用域中依然没有,则会报错ReferenceError
- 在函数中想要访问全局的变量可以使用window
4.5.3 变量的声明提前
- 在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。
- 所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。
console.log(a); // undefined
var a = 10;
console.log(a); // error
a = 10;
- 在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明,但是不会被提前赋值。
fun(); // "fun函数"
fun2(); // Uncaught TypeError: fun2 is not a function
// 函数声明会被提前创建
function fun(){
console.log("fun函数");
}
// 函数表达式不会被提前创建
var fun2 = function(){
console.log("fun2函数");
}
- 如果没有使用var关键字声明变量,则变量会变成全局变量。
var a =5 ;
function fun(){
a = 10;
}
fun()
console.log(a); // 10
- 定义形参都相当于在函数作用域中声明了变量。
4.6 this(上下文对象)
-
我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。
-
使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。
-
指向当前对象
-
this的不同的情况:
(1)以函数的形式调用时,this是window
(2)以方法的形式调用时,this就是调用方法的对象
(3)以构造函数的形式调用时,this就是新创建的对象
var name = "window name";
var obj1 = {
name:"obj1 name",
sayName:fun
};
var obj2 = {
name:"obj2 name",
sayName:fun
};
function fun(){
console.log(this.name);
}
fun(); // window name
obj1.sayName();// obj1 name
obj2.sayName();// obj2 name
4.7 原型(prototype)
- 创建一个函数以后,解析器都会默认在函数中添加一个属性prototype
- prototype属性指向的是一个对象,这个对象我们称为原型对象。
- 当函数作为构造函数使用,它所创建的对象中都会有一个隐含的属性执行该原型对象。
这个隐含的属性可以通过对象.__proto__来访问。
- 原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。
- 我们可以将对象中共有的属性和方法统一添加到原型对象中,这样我们只需要添加一次,就可以使所有的对象都可以使用。
- 当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,
- 如果在自身中找到了,则直接使用。
- 如果没有找到,则去原型对象中寻找,如果找到了则使用,
- 如果没有找到,则去原型的原型中寻找,依此类推。直到找到Object的原型为止,Object的原型的原型为null,
- 如果依然没有找到则返回undefined
function MyClass(){
}
MyClass.prototype.a = 123;
var mc = new MyClass()
-hasOwnProperty()
- 这个方法可以用来检查对象自身中是否含有某个属性
语法:对象.hasOwnProperty(“属性名”)