JavaScript学习笔记(4)——对象、函数


前言

本篇学习对象与函数。


一、对象

笔记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视频整理而成。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值