一、对象的基本使用
1.1 认识对象类型
-
对象类型是一种存储键值对(key-value)的复杂数据类型
- 对象类型可以使用{…}来创建的复杂类型,里面包含的是键值对(“key: value”)
- 键值对可以是属性和方法(在对象中的函数称之为方法)
- 其中key是字符串(也叫做属性名property name ,ES6之后也可以是Symbol类型,后续补充)
- 其中value可以是任意类型,包括基本数据类型、函数类型、对象类型等
// key: 字符串类型, 但是在定义对象的属性名时, 大部分情况下引号都是可以省略的 var person = { // key: value name: "kobe", age: 24, height: 1.98, "friend": { name: "james", age: 30 }, run: function() { console.log("running") }, eat: function() { console.log("eat foods") }, study: function() { console.log("studying") } }
1.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() - 对象字面量(Object Literal):通过
1.3 对象的操作过程
- 获取属性
- 修改属性
- 新增属性
- 删除属性
-
delete 删除操作符
// 1.定义了一个对象 var info = { name: "kobe", age: 20, friend: { name: "james", 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)
-
1.4 方括号的用法
-
点符号要求
key是有效的变量标识符- 不包含空格,不以数字开头,也不包含特殊字符(允许使用 $ 和 _)
-
对于特殊的属性可以使用方括号访问:
- 方括号在定义或者操作属性时更加的灵活
var obj = { name: "kobe", "my friend": "james", "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]()
1.5 对象的遍历方式
-
对象的遍历(迭代):表示获取对象中所有的属性和方法。
- Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组
-
普通for循环
-
for in 遍历方法
var info = { name: "kobe", age: 24, height: 1.98 } // 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) { // }
二、内存分配
2.1 内存概念理解
-
栈内存 / 堆内存
- 原始类型占据的空间是在栈内存中分配的
- 对象类型占据的空间是在堆内存中分配的
-
值/引用类型的分配
- 原始类型的保存方式:在变量中保存的是值本身,所以原始类型也被称之为值类型
- 对象类型的保存方式:在变量中保存的是对象的 “引用”,所以对象类型也被称之为引用类型
2.2 一些现象的内存表示
-
两个对象的比较
-
引用赋值
-
值传递
-
引用传递,在函数中创建了一个新对象,没有对传入对象进行修改
-
引用传递,对传入的对象进行修改
三. this的使用
3.1 this到底指向什么
-
目前掌握两个
this的判断方法:- 以默认的方式调用一个函数,this指向window
- 通过对象调用,this指向调用的对象
// 函数中是有一个this的变量, this变量在大多数情况下会指向一个对象 // arguments保存的是传入的所有参数 // 情况一: 如果普通的函数被默认调用, 那么this指向的就是window function foo(name, age) { console.log(arguments) console.log(this) // window } foo("abc", 123) function sayHello(name) { console.log(this) // window } // 情况二: 如果函数它是被某一个对象来引用并且调用它, 那么this会指向这个对象(调用的那个调用) var obj = { name: "zhangsan", running: function() { console.log(this) // obj对象 // console.log(obj) // console.log(this === obj) // true } } obj.running()// 1.题目一: var fn = obj.running fn() // window // 2.题目二: function bar() { console.log(this) // obj对象 } var obj = { name: "why", bar: bar } obj.bar()
- 后续补充其他
this规律
3.2 this的作用
-
方便在一个方法中,拿到当前对象的一些属性
var info = { name: "zhangsan", age: 38, 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()
四、面向对象-创建一系列对象
4.1 对象字面量
-
弊端: 重复代码
// 一系列的学生对象 // 重复代码的复用: for/函数 var stu1 = { name: "zhangsan", age: 18, height: 1.88, running: function() { console.log("running~") } } var stu2 = { name: "lisi", age: 22, height: 1.98, running: function() { console.log("running~") } } var stu3 = { name: "wangwu", age: 20, height: 1.77, running: function() { console.log("running~") } }
4.2 工厂函数
-
封装一个函数,这个函数用于帮助创建一个对象,创建一系列对象只需要重复调用这个函数即可
-
工厂模式其实是一种常见的设计模式
-
问题:
- 在打印对象时,对象的类型都是
Object类型,从某种角度来说,这些对象应该有一个他们共同的类型
// 工厂函数(工厂生产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("zhangsan", 18, 1.88) var stu2 = createStudent("lisi", 22, 1.98) var stu3 = createStudent("wangwu", 20, 1.77) console.log(stu1) console.log(stu2) console.log(stu3) - 在打印对象时,对象的类型都是
4.3 构造函数
-
什么是构造函数?
- 构造函数也称之为构造器(constructor),通常是我们在创建对象时会调用的函数
- 在其他面向的编程语言里面,构造函数是存在于类中的一个方法,称之为构造方法
- 但是JavaScript中的构造函数有点不太一样,构造函数扮演了其他语言中类的角色
-
new操作符:
- 在内存中创建一个新的对象(空对象)
- 这个对象内部的
[[prototype]]属性会被赋值为该构造函数的prototype属性(后续会补充) - 构造函数内部的this,会指向创建出来的新对象
- 执行函数的内部代码(函数体代码)
- 如果构造函数没有返回非空对象,则返回创建出来的新对象
// JavaScript已经默认提供给了我们可以更加符合JavaScript思维方式(面向对象的思维方式)的一种创建对象的规则 // 在函数中的this一般指向某一个对象 function coder(name, age, height) { this.name = name this.age = age this.height = height this.running = function() { console.log("running~") } } // 在函数调用的前面加 new 关键字(操作符) var stu1 = new coder("zhangsan", 18, 1.88) var stu2 = new coder("lisi", 30, 1.98)
4.4 类和对象的关系
- 在JavaScript中,构造函数其实就是类的扮演者:
- 构造函数也称之为构造器(constructor),通常是我们在创建对象时会调用的函数
- 比如系统默认给我们提供的Date就是一个构造函数,也可以看成是一个类
- 在ES5之前,我们都是通过
function来声明一个 构造函数(类) 的,之后通过new关键字来对其进行调用 - 在ES6之后,JavaScript可以像别的语言一样,通过
class来声明一个类
- 关系
- 类是一系列的描述/图纸
- 应该具备属性/行为
- 对象是根据类,具体创建出来的
- 类是一系列的描述/图纸
- 编程范式: 面向对象的编程范式
4.5 构造函数的使用
- JavaScript中的构造函数是怎么样的?
- 构造函数也是一个普通的函数,从表现形式来说,和千千万万个普通的函数没有任何区别
- 如果这么一个普通的函数被使用
new操作符来调用了,那么这个函数就称之为是一个构造函数
-
构造函数的使用大驼峰(首字母会大写)
// 创建一系列的对象 // 构造函数的名称: 使用大驼峰 function Person() { } var p1 = new Person() console.log(p1) // 平时创建普通的对象 // new Object() var obj1 = {} var obj2 = new Object() var obj3 = new Person() // 普通函数: 使用小驼峰 function sayHello() { }
- 构造函数还有很多其他的特性(后续补充)
- 原型、原型链、实现继承的方案
- ES6中类、继承的实现
五、对象的补充
5.1 全局对象window
-
作用一: 查找变量时, 最终会window头上
-
作用二: JavaScript/浏览器默认提供一些变量/函数/类, 提供到window中
-
作用三: var定义变量会被添加到window上
// 浏览器中存在一个全局对象object -> window console.log(window) // 使用var定义变量 var message = "Hello World" function foo() { // 自己的作用域 // abc() // alert("Hello World") console.log(window.console === console) // true // 创建一个对象 // var obj = new Object() console.log(window.Object === Object) // true // DOM console.log(document) // window.message console.log(window.message) } foo()
5.2 函数也是一个对象类型
// 定义原始类型的变量
var name = "kobe"
var age = 18
// 定义对象类型的变量
// 地址 - 指针 - 引用
var obj = {} // 堆内存
var foo = function() {} // 堆内存
function bar() {} // 堆内存
console.log(typeof obj) // object
console.log(typeof foo) // function -> object
// var stu = new Student() // stu是一个Student -> Person
// 引申一些别的知识
var info = {}
info.name = "abc"
function sayHello() {
}
sayHello.age = 18
console.log(sayHello.age)
function Dog() {
}
// 构造函数上(类上面)添加的函数, 称之为类方法
Dog.running = function() {}
Dog.running()