1. 对象
已经有了五种数据类型,为什么我们还需要对象?
基本数据类型值单一,值与值之间没有联系(不是一个整体)
对象的作用就是**将多个值放在一起,批量操作;
对象属于复合数据类型,可保存多个不同数据类型的属性,就像一个袋子。
1-2)对象的类型
(1) 内建对象
由Es标准中定义的对象,在任何Es实现中都可以使用 例如:
Math、String、Number、Boolean、Function,Object
问题:String、Number、Boolean数据类型与String、Number、Boolean内建对象有何区别?
(2) 宿主对象
由Js环境提供的对象,目前主要指由浏览器提供的对象。
例如: BoM,Dom; console.log就是一个对象,
document.write也是一个对象,这个两者都由浏览器提供。
(3) 自定义对象 (开发人员自己创建的对象)
// 使用new关键字调用的函数,是构造函数constructor; ;构造函数时专门用来创建对象的。
创建对象: var obj = new Object()
添加属性: obj.name= "Eric" ; 对象改值与添加一样的。
注意: 读取对象中没有的属性,不会报错,而是undefined!
删除对象属性: delete obj.name
对象属性名,属性值
对象属性名不强制要求遵守标识符规范,什么乱七八糟的命都可以,但还是尽量按标识符的规范去做。
使用特殊属性名、语法,不能例如 obj.123
正确写法: Obj["123"] = 789 ; obj["@#^%GK"] = 666;
使用[]操作对象属性,更加灵活,[]可传变量,例如var n = "123",
这样可以随时更改, console.log(obj[n]);
对象属性值
对象的属性值可以是任意的数据类型,甚至可以是一个对象。
例如: var obj = new Object();
obj.test = true;
obj.test = undefined;
var obj2 = new Object(),
obj.test = obj2 // 袋中袋
对象中没有的属性不报错,而是undefined,那么如何检查一个对象中是否有指定属性?
console.log("test" in obj ) // 有返回true, 无返回false
深浅拷贝
浅拷贝针对于引用数据类型(复杂数据类型Object (object,array, function))
浅拷贝原因: 只拷贝了堆空间地址,而未开辟新的内存空间,两处堆内存空间地址指向一处 堆内存空间。一处变化,另一个跟着变化。
为什么叫引用数据类型?
对象保存在堆空间当中,栈空间只保存了变量名和 指向堆内存空间的地址,变量名和堆空间由地址建立联系。(地址即引用)
每当var obj = new Object();就在堆空间开辟了内存空间。
两个堆内存空间,即使里面的值一模一样他们也不相同,因为空间地址不一样。
**基本数据类型直接在栈空间存储,变量值是对立存在的,修改一个值,对其他值没有任何影响。
*** 比较基本数据类型,比较的是值;(基本在栈中存->值)
比较引用数据类型,比较的是空间地址。即便里面的东西一样但内存地址不一样,那还是不一样!(引用在栈中存->空间地址)
对象字面量
var obj = {}; console.log(type of obj) [object object];
使用var obj = {} 与var obj = new Object(); 本质上一样;
对象字面量的属性,引号可以不加,也建议不加,若使用奇怪的名,必须加!
名和值用:分隔,多个属性用逗号隔开;
2. 函数 (也是对象)
除基本数据类型,剩下的都是对象
普通的对象只能装东西,而函数却还能封装一些功能,在需要时执行这些功能(代码);
封装的函数一定程度上简化了代码量;
封装: 存起来,用的时候(调用)很简单;
(1) 将要封装的代码,以字符串形式传递给构造函数;// ??不太明白
(2) 封装的函数不会立即执行,调用时执行;
(3) 调用 :fun() ;调用时,函数中的代码以顺序执行;
2-1)创建一个对象
(1) 构造函数创建对象
var fun = new Function(); // console.log(typeof fun ) "function"
补充: fun.name = "hello" 也是可以存在函数中的;
函数拥有普通对象的一切功能,但比所有普通对象更强大!
在开发中很少使用 (var fun = new Function();)构造函数创建对象;
(2) 使用函数声明创建一个函数
function 函数名(形参1, 形参2){}
function fn([..,..]){}, 套[]表可选,写不写都行。// ??? 不太明白
构造函数创建对象与函数声明创建一个函数的区别及函数声明创建一个函数的优越性?
...
(3) 使用函数表达式创建一个函数
let fn1 = funtion(形参1, 形参2){};
funtion fn2(a, b){a+b} 相当于在函数内部声明变量
var a ,var b 但未赋值,实参会赋值给函数中对应的形参;
调用函数,解析器不会检查实参类型;传数值会计算,fn2(1,3) // 4
传(123,"hello") -> 123hello;
传(true, false) -> 1
因此要注意是否会接收到不合法的参数,若有可能,最好对参数类型检查。
调函数,也不会检查实参数量,多余的实参不会被赋值,因为函数中只有a+b,多传也是a+b的结果;
函数实参可以是任意数据类型;
若实参数量少于形参,则没有对应实参的形参,将会是undefined,funtion fn2(a, b){a+b}, a+b结果为NAN;
函数必须有返回值!
return 将作为函数的执行结果返;return后的代码不再执行;
return 后不写任何值,相当于返回undefined, 同不写return;
return 后可以跟任意类型的值;
例: function sum(a, b, c){
var d = a+b +c
return d
}
sum(11,22,33)
var result = sum(11,22,33) // 这样更加灵活,函数返回什么值,result结果就是什么;
alert()是函数;
函数实参可以是任何值,也可以是对象;
参数过多,可以将参数封装到一个对象里,再通过 对象.属性值拿值;
函数也可以作为函数的参数;fn(main()) 相当于把函数的返回值放进去了;
fn(main)相当于把函数放进去 (机器)
break退出循环体,for停止;return结束函数;
函数内部可无限声明函数;
函数的键值
var a = fn3();
console.log(a.name)
自执行函数: (往往只执行一次)
(function(){})()
对象属性值可为任何数据类型,亦可以是一个函数;
var obj = new Object();
obj.name = "牛恒";
obj.sayname = function() {
console.log(obj.name)
}
obj.sayname() // 牛恒 (调方法)
sayname() // 调函数 ,这两种,只是叫法不一样,无本质区别
若函数作为对象的一个属性保存,那么就称 *** 这个函数是这个对象的方法。调用函数就叫调用对象的方法(methods)。
3. 枚举 (将对象的属性一个个取出)
// 使用for in
var obj = {
name:"wind",
age: "24"
}
// 语法:
for(var n in obj) {
console.log('hello') // 有几个键,(打印几次),循环就会执行几次,每次执行都会将对象的属性赋值给变量 n
}
// n = name 第一次
// n = age 第二次