文章目录
对象 (Object)
1.1 对象
基本数据类型都是一个一个独立的值,值与值之间不存在任何的联系。这样就导致无法在程序中表示一些复杂的数据。
基本数据类型(不可变类型)
- 字符串(string)
- 数值(number)
- 布尔值(Boolean)
- 空值(null)
- 未定义(undefined)
复杂数据类型
- 对象(Object)
对象就是 JS 中的一种数据类型。
对象相当于是一个容器(复杂数据类型),在对象中可以存储不同类型的数据
对象中存储的数据被称为属性,向对象中添加数据称为添加属性
//创建一个空的对象
var obj = new Object(); //var obj = Object(); 是一样的,new可以省略
console.log(obj); // {}
//向对象中添加属性:
// 对象.属性名 = 属性值;
obj.name = "孙悟空";
obj.age = 18;
obj.gender = "男";
console.log(obj); //{name:"孙悟空",age:18,gender:"男"}
//读取对象中的属性:
// 对象.属性名
console.log(obj.name); // 孙悟空
console.log(obj.age); // 18
console.log(obj.gender); // 男
console.log(obj.address); //undefined 当我们访问一个对象中没有的属性时,不会报错而是返回undefined
//删除属性
// delete 对象.属性名
delete obj.name;
console.log(obj.name); // undefined
1.2 属性
1.2.1 属性名
属性名:
对象的属性是任意值,不必要遵循标识符的规范(不推荐)。尽量遵循标识符的规范。
var obj = Object();
obj.name = "孙悟空";
console.log(obj.name); //孙悟空
特殊的命名方式:
对象["属性名"] = 属性值
obj.12312!@#@#!sdasdasff = "孙悟空"; //这样命名导致报错
obj.["12312!@#@#!sdasdasff"] = "孙悟空"; // 这样就可以成功 (不推荐这样使用)
读取属性的第二种方式:
对象['属性名'] // 这种方式读取属性更加灵活
console.log(obj.["12312!@#@#!sdasdasff"]); // 孙悟空
console.log(obj.["name"]); // 孙悟空
灵活例子:
var obj = object();
obj.name = "孙悟空";
obj.age = 18;
obj.gender = "男";
var a = "name";
console.log([a]); // 孙悟空
var a = "age";
console.log([a]); // 18
//根据变量的值不同 读取的结果也不一样。注意:[a] 不能变成 ["a"],["a"]就变成读取对象中的a属性
1.2.2 属性值
对象的属性值可以是任意的数据类型
obj.test = null;
obj.test = true;
obj.test = "字符串";
obj.test = 123456;
obj.test = Object();
1.2.3 属性枚举
var obj = Object();
obj.name = "孙悟空";
obj.age = 18;
//在开发中对象可能是读取来的,不知道对象里有什么属性
//检查一个对象中是否有某个属性
// in 运算符 用来检查对象是否有某个属性
// 有符号 true 没有返回false
语法:
'属性名' in 对象
console.log('name' in obj); // true
//而枚举就是将对象中的属性全部提取出来,对象中有几个属性就会执行几次
//每次执行都会将一个属性赋值给我们定义的变量
语法:
for (var 变量 in 对象){
语句...
}
for(var n in obj){
console.log(n); // 见下图1
}
//当需要属性值时
for(var n in obj){
console.log(obj.n); // 见下图2
}
// obj.n 表示去读取 obj 中 n 的属性,但是 obj 中没有 n 的属性所以是 undefined
//虽然在 for in 中每一次循环会把属性赋值给 n ,但 n 是一个变量
for(var n in obj){
console.log(obj.[n]); // 见下图3
}
1.3 对象字面量
var obj = Object();
var obj = new Object();
都是创建一个对象
以字面量来创建对象:
var obj = {};
- 字面量可以在创建对象时直接向对象中添加属性
- var obj = {name:"孙悟空",age=18}; // 不同属性之间逗号隔开,最后一个属性后不要写逗号
函数 (function)
函数也是一个对象和其他的对象功能一样
不同的是在函数中可以直接存储JS代码
并且可以在我们需要的时候对这些代码进行反复的调用
2.1 声明函数
创建函数:
function 函数名(){
语句...
}
function fn(){ // fn 函数的名字,起名规范也要遵循
console.log('声明函数');
}
函数调用:
fn(); // 函数对象名 + () 调用函数
2.2 匿名函数
函数表达式: (匿名函数)
var 变量 = function(){
语句...
};
var a = function(){
console.log('匿名函数');
};
函数调用:
a();
2.3 立即执行函数
会在函数创建后立即调用,并且只会调用一次
//JS 禁止一个以function开头的函数没有名字
/*function(){
当这样写时会报错误
}*/
所以给函数加一个括号:
(function(){console.log("我是一个匿名函数")});
调用:
1.(function(){console.log("我是一个匿名函数")})(); // 直接尾部括号调用
2.(function(){console.log("我是一个匿名函数")}()); // 括号里面调用
2.4 参数(形参、实参)
形参(形式参数):
//定义函数时,可以在函数的()中指定数量不等的形参
//定义形参就相当于在函数中声明了两个变量,但没有赋值
function sum(a,b){
console.log("a=",a,"b=",b); //见下图1
}
function sum(){
console.log("a=",a,"b=",b); //见下图2
}
实参(实际参数):
//在调用函数时,可以在函数的()中传递数量不等的实参
//实参将会赋值给对应的形参
sum(1,2); // 见下图3
sum("hello","abc"); // 见下图4
//在JS中不会检查实参的类型和数量,可以传递任意类型的实参
//不同类型:
sum(true,false); // 1+0 = 1
sum(123,'456'); // 字符串拼接 123456
sum(null,undefined) // NaN
//不同数量:
//实参数量和形参数量相同,则对应赋值
sum(1,2); // a = 1, b = 2
//实参少于形参,则没有实参的形参默认为undefined
sum(1); // a = 1, undefined
//实参多余形参,则多余的实参不会使用
sum(1,2,3,4) // a = 1, b = 2
2.5 函数的返回值
返回值:
返回值就是函数的执行结果
通过 return 来设置函数的返回值
语法:
return 值;
function sum(a,b){
return 123;
}
//调用函数时,返回值就是函数的执行结果,可以定义一个变量来接受结果
var a = sum(123,456); // 把 sum 的返回值赋值给了 a
console.log(a); // 123
//任何值都可以作为函数的返回值
function fn(){
return {};
return {name:"孙悟空"};
return function(){
console.log("内部函数")
}
return 数字、字符串、布尔值...
}
// 如果不设置return或者return 不跟任何值,则相当于return一个undefined
function fn(){
//什么也没有写
}
var result = fn();
console.log(result); // undefined
//return 之后所有的代码都不会执行,return之后函数结束。
function fn(){
return;
console.log("return之后的代码"); // 这个并不会在控制台输出显示
}
var result = fn();
console.log(result); // undefined
2.6 方法
//任何值都可以成为对象的属性,函数也不例外
//如果一个对象的属性是函数
//则我们称这个函数是这个对象的方法(method)
var obj = {
test:function(){
alert("我是obj中的函数");
}
}
obj.test() // 调用了obj的test方法
2.7 作用域
作用域:
- 作用域指的就是变量的作用范围
- 作用域分两大类
1.全局作用域
2.局部作用域
- 块作用域
- 函数作用域
2.7.1 全局作用域
全局作用域在页面加载时创建,页面关闭时销毁。
所有直接写在script标签中的内容,都位于全局作用域中。
全局作用域中定义的变量是全局变量,定义的函数是全局函数。可以在任意位置被访问到。
全局作用域中存在一个全局对象 : window , window对象代表浏览器窗口
<script>
let a = 10; //全局变量
let b = 20; //全局变量
function fn(){ // 全局函数
coonsole.log(a);
coonsole.log(b);
}
fn();
</script>
在全局作用域中,所有使用 var 声明的变量都会作为全局对象的属性保存
使用function声明的函数都会作为window对象方法保存
<script>
var a = 10; // 这个时候就是window的属性被保存
var b = 20;
let c = 30; // let 声明不会存储在window对象里面
function fn(){
coonsole.log(a);
coonsole.log(b);
}
console.log(window.a); // 10 这个其实指的就是 var 声明的 a
console.log(window.c); // undefined
//直接为一个没有声明的变量赋值,实际就相当于直接向window对象中添加属性
d = 30; // window.d = 30
</script>
2.7.2 函数作用域
函数作用域在函数调用时创建,调用结束时销毁`
函数每次调用都会产生一个新的函数作用域,每个作用域之间都是相互独立的
//在函数作用域中声明的变量是局部变量,只能在函数内部访问,外部无法访问
function fn(){
let a = 10;
var b = 20; // var 和 let 在局部声明中其实没有什么区别,外部都不能访问
//在函数中声明变量不使用声明,则变量会成为一个全局变量(注意!!!)
c = 30;
console.log(a,b);
}
fn(); //调用函数则打印 a 和 b 的值 = 10 20
// 在函数外面访问函数内部的变量
console.log(a,b); // 报错 a is not defined
//得到函数中 c 的值
console.log(c); // 30
2.7.3 作用域链
// 函数作用域
let a = 10;
function fn(){
console.log(a); // 访问外部的 a ,得到值
}
fn(); // 10
// 作用域链
let a = 10;
function fn(){
let a = 20;
//当我们访问一个变量时,JS 会先在当前作用域中寻找,在函数作用域中有 a ,所以输出函数作用域的 a 的值,如果没有则去当前作用域的上一层去寻找,以此类推到全局作用域,没有则报错 xxx is not defined
console.log(a);
}
fn(); // 20
函数定义在哪里,它的上一层作用域就在哪里
let b = 22;
function fn2(){ // 定义位置
console.log("b=", b); //b = 22
// JS中的作用域叫做 词法作用域,函数作用域由它定义的位置来决定的,和调用位置无关
}
function fn3(){
let b = 33;
//虽然在 fn3 函数作用域中调用,对于 fn2 来说,fn2 的作用域上一层依然是全局作用域,因为 fn2 定义位置在全局作用域中
fn2(); // 调用位置
}
fn3();
2.8 变量的提升
a = 10;
console.log(a); // 10
此时 a 的值是 10,
console.log(a); // 错误: a is not defined
a = 10;
a is not defined 使用了没有声明的变量报的错误,这个时候给这个变量声明
// var a; 相当于在打印前已经声明了一个a
console.log(a); // undefined
var a = 10;
在 JS 中,使用 var 声明的变量会在所有的代码执行前被创建,相当于在打印 a 之前已经先声明了 a,结果是undefined的原因是因为赋值还没有执行。这个特点称为变量的提升。
函数也是一样的,也会被提升
fn();
//声明函数
function fn(){
console.log("函数1");
}
// 这个时候就会打印输出 : 函数1
fn2(); // fn2 is not function
//函数表达式
var fn2 = function(){
console.log("函数2");
}
fn2(); // 函数2
var 在 function 的前面,提升的是 var 声明的 fn2 , 所以在前面调用 fn2 这个函数时,会报错。
而在这个函数之后调用,那么因为已经给 fn2 进行了赋值,所以输出函数2。