文章目录
前言
本篇学习对象与函数。
一、对象
笔记2中的五个数据类型属于基本数据类型,这些数据类型变量都是独立的
对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性
1.对象的分类
①内建对象
由ES标准中定义的对象,在任何的ES的实现中都可以使用
例如:Math String Number Boolean Function Object…
②宿主对象
由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
比如 BOM DOM
③自定义对象
由开发人员自己创建的对象
创建对象
使用new调用构造函数,构造函数是专门用来创建对象的函数
添加属性:
对象.属性名=属性值
如果读取对象中没有的属性,不会报错而是会返回undefined
删除对象的属性:
delete 对象.属性名
属性名:对象的属性名不强制要求遵守标识符的规范,但是尽量按照标识符的规范定义(不混乱)
如果要使用特殊的属性名,不能采用.的方式,需要使用另一种方式:
对象[“属性名”] = 属性值
读取时也需要采用这种方式
使用[ ]这种形式去操作属性,更加的灵活,在[ ]中可以直接传递一个变量,这样变量值是多少就会读取那个属性
var obj = new Object();
obj["123"] = 789;
obj["nihao"] = "你好";
var n = "nihao";
console.log(obj[n]); //输出"你好"
属性值:可以是任意的数据类型,甚至也可以是一个对象
in 运算符,通过该运算符可以检查一个对象中是否含有某个属性
如果有则返回true,没有则返回false
“属性名” in 对象
console.log("test" in obj);
console.log("name" in obj);
枚举对象属性
for(var n in obj){
console.log("属性名:"+n);
console.log("属性值:"+obj[n]); //这里注意用法,用[n]
}
对象中有几个属性,循环体就会执行几次
每次执行时,会将对象中的一个属性名赋值给变量
JS中的变量都是保存到栈内存中的,基本数据类型的值直接在栈内存中存储。值与值之间是独立存在,修改一个变量不会影响其他的变量
对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而栈内存中的对象变量的值是对象的内存地址(对象的引用)。如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响
比较两个基本数据类型的值时,就是比较值。
比较两个引用数据类型时,它是比较的是对象的内存地址
2.对象字面量
使用字面量创建对象
var obj = {
属性名:属性值,
属性名:属性值…
};
对象字面量的属性名可以加引号也可以不加,建议不加,本身就是记为String。如果要使用一些特殊的名字,则必须加引号
var obj = {
name:"孙悟空",
age:13,
gender:"男",
test:{name:"美猴王"} //这是个对象
};
二、函数
函数也是对象
函数中可以保存一些代码,在需要的时候调用
使用typeof检查一个函数对象时,会返回function
1.创建函数对象的三个方法
①用构造函数创建(用的少)
var fun1 = new Function("console.log('Hello 这是我的第一个函数');");
②用函数声明创建
function 函数名([形参1,形参2...形参N]){
语句1
}
function fun2(){
console.log("这是我的第二个函数~~~");
document.write("你今天真好看!");
}
③用匿名函数创建(函数表达式)
先创建匿名函数,再赋值给变量
var fun3 = function(){
console.log("我是匿名函数中封装的代码");
}; //注意分号,赋值语句
调用函数
语法:函数对象()
fun3().
fun2();
2.函数的参数
可以在函数的( )中来指定一个或多个形参,声明形参就相当于在函数内部声明了对应的变量,但并不赋值
形参
定义函数时的参数
实参
调用函数时传入的参数
调用函数时解析器不会检查实参的类型,不会检查实参的数量,注意:是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查
函数的实参可以是任意的数据类型
多余实参不会被赋值
如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined
3.函数的返回值
return 值
return后的语句都不会执行
如果return语句后不跟任何值就相当于返回一个undefined,如果函数中不写return,则也会返回undefined
return后的值可以是任意的类型(包含对象、函数)
在函数内部可以再声明/调用函数
function fun3(){
//在函数内部再声明一个函数
function fun4(){
alert("我是fun4");
}
//将fun4函数对象作为返回值返回
return fun4;
}
a = fun3();
4.函数的实参
当函数形参很多的时候,可以将参数封装到对象中,避免形参很多造成参数混乱丢失的情况
对象可以作为实参传入函数
function sayHello(o){
console.log("我是"+o.name+",今年我"+o.age+"岁了,"+"我是一个"+o.gender+"人"+",我住在"+o.address);
}
//创建一个对象
var obj = {
name:"孙悟空",
age:18,
address:"花果山",
gender:"男"
};
sayHello(obj);
实参也可以是一个函数
function fun(a){
console.log("a = "+a);
a(obj);
}
fun(sayHello); //实参为sayHello函数
fun(function(){alert("hello")}); //实参是匿名函数
sayHello(),调用函数,是函数的返回值
sayHello,函数对象,直接使用函数对象
5.立即执行函数
定义完函数后立即执行
一般是匿名函数,只执行一次
匿名函数加括号表示一个整体
(function(a,b){
console.log("a = "+a);
console.log("b = "+b);
})(123,456); //直接在这里加(123,456),传入实参,调用匿名函数
6.方法与函数
对象的属性值:可以是任意的数据类型,甚至也可以是一个对象,也可以是函数
如果一个函数作为一个对象的属性保存,那么可以称这个函数是这个对象的方法,调用这个函数就说调用对象的方法
但是调函数和调方法只是名称上的区别,没有其他的区别(下面实现了一样的功能)
var obj = new Object();
obj.name = "孙悟空";
obj.age = 18;
obj.sayName = function(){
console.log(obj.name);
};
function fun(){
console.log(obj.name);
};
//调方法
obj.sayName();
//调函数
fun();
调用方法就是对象.函数()
三、作用域
1.全局作用域
直接编写在script标签中的JS代码,都在全局作用域
全局作用域在页面打开时创建,在页面关闭时销毁
在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建,我们可以直接使用
在全局作用域中,创建的变量都会作为window对象的属性保存,创建的函数都会作为window对象的方法保存
* - 全局作用域中的变量都是全局变量,
* 在页面的任意的部分都可以访问的到
var a = 10;
var b = 20;
console.log(window.a); //显示10
function fun(){
console.log("我是fun函数");
}
window.fun();
其实函数就是window对象的方法*
变量声明提前
使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值)
但是如果声明变量时不适用var关键字,则变量不会被声明提前
console.log("a = "+a); //显示undefined
var a = 123; //这里如果没有var,则不能执行,直接报错
函数声明提前
使用函数声明形式创建的函数 function 函数(){},它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数
使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用
fun(); //可执行
console.log(fun2); //显示undefined
//函数声明,会被提前创建
function fun(){
console.log("我是一个fun函数");
}
//函数表达式,不会被提前创建
var fun2 = function(){ //fun2这个变量会被提前声明
console.log("我是fun2函数");
};
fun2();
2.函数作用域
调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的
在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量
当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(就近原则),如果没有则向上一级作用域中寻找,直到找到全局作用域
如果全局作用域中依然没有找到,则会报错ReferenceError
在函数中要访问全局变量可以使用window对象
var a = 10;
function fun(){
var a = "我是fun函数中的变量a";
console.log("a = "+a); //显示"我是fun函数中的变量a"
function fun2(){
console.log("a = "+window.a);
}
fun2(); //显示a=10
}
在函数作用域也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明。函数声明也会在函数中所有的代码执行之前执行
var a = 10;
function fun3(){
fun4(); //显示"I'm fun4"
console.log(a); //显示undefined
var a = 35;
//函数声明
function fun4(){
alert("I'm fun4");
}
}
在函数中,不使用var声明的变量都会成为全局变量
var c = 33;
function fun5(){
console.log("c = "+c); //显示33,而不是undefined,因为去上级找到了33
c = 10; //改变了全局变量
d = 100; //d没有使用var关键字,则会设置为全局变量
}
fun5();
console.log("c = "+c); //显示10,函数内对全局变量c进行了修改
console.log("d = "+d); //显示100,c是全局的,前提是fun5在前面被调用了,如果不提前调用的话,这里报错
定义形参就相当于在函数作用域中声明了变量
var a = 123;
function fun(a){
alert(a); //显示undefined
a = 456; //这里修改的是形参a
}
fun();
alert(a); //显示123
总结
本篇针对对象、函数进行总结,可以看到知识点还是很复杂且交错的,此外包含作用域等其他内容。
根据尚硅谷李立超老师2019年的JS视频整理而成。