JavaScript对象
对象的基本使用
4.1. 认识对象类型
// key: 字符串类型, 但是在定义对象的属性名时, 大部分情况下引号都是可以省略的
var person = {
// key: value
name: "why",
age: 18,
height: 1.88,
"my friend": {
name: "kobe",
age: 30
},
run: function() {
console.log("running")
},
eat: function() {
console.log("eat foods")
},
study: function() {
console.log("studying")
}
}
4.2. 对象的创建方式
- 对象字面量(Object Literal):
- 通过new Object+动态添加属性;
- new 其他类;
// 1.对象字面量
var obj1 = {
name: "why"
}
// 2.new Object()
// // Object构造函数
var obj2 = new Object()
obj2.name = "kobe"
// // 3.new 其他类()
function Person() {}
var obj3 = new Person()
4.3. 对象的操作过程
- 获取属性
- 修改属性
- 新增属性
- 删除属性
- delete
// 1.定义了一个对象
var info = {
name: "why",
age: 18,
friend: {
name: "kobe",
age: 30
},
running: function() {
console.log("running~")
}
}
// 2.访问对象中的属性
// console.log(info.name)
// console.log(info.friend.name)
// info.running()
// 3.修改对象中的属性
// info.age = 25
// info.running = function() {
// alert("I am running~")
// }
// console.log(info.age)
// info.running()
// 4.添加对象中的属性
info.height = 1.88
info.studying = function() {
console.log("I am studying~")
}
console.log(info)
// 5.删除对象中的属性
// delete关键字(操作符)
delete info.age
delete info.height
console.log(info)
4.4. 方括号的用法
- 为什么需要使用方括号呢?
- 这是因为点符号要求 key 是有效的变量标识符
- 不包含空格,不以数字开头,也不包含特殊字符(允许使用 $ 和 _);
var obj = {
name: "why",
"my friend": "kobe",
"eating something": function() {
console.log("eating~")
}
}
console.log(obj["my friend"])
console.log(obj.name)
console.log(obj["name"])
// obj["eating something"]()
var eatKey = "eating something"
obj[eatKey]()
4.5. 对象的遍历方式
- 普通的for循环
- Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组;
- for...in...
- for...of...(不支持):默认是不能遍历对象
var info = {
name: "why",
age: 18,
height: 1.88
}
// console.log(Object.keys(info))
// 对对象进行遍历
// 1.普通for循环
var infoKeys = Object.keys(info)
for (var i = 0; i < infoKeys.length; i++) {
var key = infoKeys[i]
var value = info[key]
console.log(`key: ${key}, value: ${value}`)
}
// 2.for..in..: 遍历对象
for (var key in info) {
var value = info[key]
console.log(`key: ${key}, value: ${value}`)
}
// 对象不支持: for..of..: 默认是不能遍历对象
// for (var foo of info) {
// }
内存分配
5.1. 内存概念理解
栈内存
- 原始类型占据的空间是在栈内存中分配的;
堆内存
- 对象类型占据的空间是在堆内存中分配的;
原始类型的保存方式:
- 在变量中保存的是值本身
- 所以原始类型也被称之为值类型;
- 对象类型的保存方式:
- 在变量中保存的是对象的“引用”
- 所以对象类型也被称之为引用类型;
5.2. 现象的内存表示
// var num1 = 123
// var num2 = 123
// console.log(num1 === num2)
// 1.现象一: 两个对象的比较
// var obj1 = {}
// var obj2 = {}
// console.log(obj1 === obj2)
// // 2.现象二: 引用的赋值
// var info = {
// name: "why",
// friend: {
// name: "kobe"
// }
// }
// var friend = info.friend
// friend.name = "james"
// console.log(info.friend.name) // james
// 3.现象三: 值传递
// function foo(a) {
// a = 200
// }
// var num = 100
// foo(num)
// console.log(num) // 100
// 4.现象四: 引用传递, 但是在函数中创建了一个新对象, 没有对传入对象进行修改
// function foo(a) {
// a = {
// name: "why"
// }
// }
var obj = {
name: "obj"
}
foo(obj)
console.log(obj)
// 5.现象五: 引用传递, 但是对传入的对象进行修改
function foo(a) {
a.name = "why"
}
var obj = {
name: "obj"
}
foo(obj)
console.log(obj)
六. this的使用
6.1. this到底指向什么
- 在全局环境下面,this指向window;
- 通过对象调用,this指向调用的对象;
// 情况一: 如果普通的函数被默认调用, 那么this指向的就是window
function foo(name, age) {
console.log(arguments)
console.log(this)
}
// 情况二: 如果函数它是被某一个对象来引用并且调用它, 那么this会指向这个对象(调用的那个调用)
var obj = {
name: "why",
running: function() {
console.log(this)
// console.log(obj)
// console.log(this === obj)
}
}
obj.running()
- 测试题
// 考验题目
// 1.题目一:
// var fn = obj.running
// fn() // window
// 2.题目二:
function bar() {
console.log(this) // obj对象
}
var obj = {
name: "why",
bar: bar
}
obj.bar()
6.2. this的作用
- 方便在一个方法中, 拿到当前对象的一些属性
var info = {
name: "why",
age: 18,
running: function() {
console.log("running~", this.name)
},
eating: function() {
console.log("eating~", this.name)
},
studying: function() {
console.log("studying~", this.name)
}
}
info.running()
info.eating()
info.studying()
对象的方式
1.1. 对象字面量
- 弊端: 重复代码
// 一系列的学生对象
// 重复代码的复用: for/函数
var stu1 = {
name: "why",
age: 18,
height: 1.88,
running: function() {
console.log("running~")
}
}
var stu2 = {
name: "kobe",
age: 30,
height: 1.98,
running: function() {
console.log("running~")
}
}
var stu3 = {
name: "james",
age: 25,
height: 2.05,
running: function() {
console.log("running~")
}
}
1.2. 工厂函数
- 一种创建对象的方式:工厂函数
- 我们可以封装一个函数,这个函数用于帮助我们创建一个对象,我们只需要重复调用这个函数即可;
- 工厂模式其实是一种常见的设计模式;
// 工厂函数(工厂生产student对象) -> 一种设计模式
// 通过工厂设计模式, 自己来定义了一个这样的函数
function createStudent(name, age, height) {
var stu = {}
stu.name = name
stu.age = age
stu.height = height
stu.running = function() {
console.log("running~")
}
return stu
}
var stu1 = createStudent("why", 18, 1.88)
var stu2 = createStudent("kobe", 30, 1.98)
var stu3 = createStudent("james", 25, 2.05)
console.log(stu1)
console.log(stu2)
console.log(stu3)
工厂方法创建对象有一个比较大的问题:
我们在打印对象时,对象的类型都是Object类型
但是从某些角度来说,这些对象应该有一个他们共同的类型;
下面我们来看一下另外一种模式:构造函数的方式;
1.3. 构造函数
在ES5之前,我们都是通过function来声明一个构造函数(类)的,之后通过new关键字来对其进行调用;
// 在函数调用的前面加 new 关键字(操作符)
var stu1 = new coder("why", 18, 1.88)
var stu2 = new coder("kobe", 30, 1.98)
console.log(stu1, stu2)
alert("Hello")
- 构造函数也是一个普通的函数,从表现形式来说,和千千万万个普通的函数没有任何区别;
- 那么如果这么一个普通的函数被使用new操作符来调用了,那么这个函数就称之为是一个构造函数;
1.4.new操作符做了什么事情
- 如果一个函数被使用new操作符调用了,那么它会执行如下操作:
- 在内存中创建一个新的对象(空对象);
- 这个对象内部的[[prototype]]属性会被赋值为该构造函数的prototype属性;(后面详细讲);
- 构造函数内部的this,会指向创建出来的新对象;
- 执行函数的内部代码(函数体代码);
- 如果构造函数没有返回非空对象,则返回创建出来的新对象;
1.5. 构造函数的使用
- 构造函数的使用大驼峰(首字母会大写)
对象的补充
2.1. 全局对象window
- 作用一: 查找变量时, 最终会window头上
- 作用二: JavaScript/浏览器默认提供一些变量/函数/类, 提供到window中
alert()
- 作用三: var定义变量会被添加到window上
2.2. 函数也是一个对象类型
function foo() {}
var bar = foo // 地址
bar()
bar.message = "Hello World"