对象是javascript
的复合数据类型。对象可看做是属性的无序集合,每个属性都是一个名/值对,属性名是任意字符串,但对象中不能存在两个同名的属性,值可以是任意类型。面向过程思维方式: 把解决问题的关注点放在每一个步骤上。面向对象思维方式: 把解决问题的关键点放在解决问题需要的一系列对象上。
对象的特点
- 属性的值(value)
- 可写(writable) 表明是否可以设置该属性的值
- 可枚举(enumerable) 表明是否可以通过for/in或for/of遍历该属性
- 可配置(configurable) 表明是否可以删除或修改该属性
- 对象的原型(prototype) 指向另外一个对象,本对象的属性继承自它的原型对象
- 对象的类(class) 是一个标识对象类型的字符串
创建对象
对象直接量(对象字面量)
1
2
3
4
5
6
7
8
9var point = {x:0, y:1}
var book = {
'title': 'Javascript',
'sub-title': 'js',
'author': {
firstname: 'Bob',
surname: 'David'
}
}通过new 构造函数()
1
2
3var obj = new Object({x:1}) // 创建一个对象 同 {x:1}
var arr = new Array(1,2) // 创建一个数组 同 [1, 2]
var d = new Date() // 创建一个表示当前时间的date对象Object.create() 创建原型对象
Object.create()
是一个静态函数,第一个参数是这个对象的原型,第二个参数为可选参数,用以对对象的属性进行进一步的描述1
2var P = {name: 'tew'}
var o3 = Object.create(P)
new 构造函数() 经历四个步骤
- 创建一个新对象
- 将构造函数的作用域赋值给新对象(this指向新对象)
- 执行构造函数中的代码(为新对象this添加属性)
- 返回新对象(默认是 return this)
获取和设置对象的属性
可以通过点(.)和方括号([])运算符来获取属性的值
1 | var book = { |
对象的方法
toString()方法 将对象转换为字符串
1
2s = {x:1, y:2}.toString();
console.log(s) // "[object Object]"toLocalString()方法 返回对象的本地化字符串
1
2
3
4
5
6var local = new Date().toLocaleString()
console.log(local) // "2017/12/26 上午14:30:14"
var date = new Date().toLocaleDateString()
console.log(date) // "2017/12/26"
var time = new Date().toLocaleTimeString()
console.log(time) // "上午14:30:14"
面向对象
- 面向对象概念: 用对象的思想去写代码,就是面向对象编程
- 面向对象特点:
- 抽象:抓住核心问题
- 封装:只能通过对象来访问方法 将一些属性和方法封装起来
- 继承:从已有对象上继承出新的对象
- 多态:多对象的不同形态,父类的成员可以共享给所有子类,子类可以给父类添加属性
- 对象:带有属性和方法的特殊数据类型
- 对象下面的变量 叫做对象的属性 状态,静态的
- 对象下面的函数 叫做对象的方法(行为,操作) 过程,动态的
创建对象
1 | var obj = new Object() |
更改this指向
- 将this用全局变量存起来
- 使用call方法改变this指向 fn.call(参数1,参数2,参数3) 参数1 可以改变函数执行过程中的this指向 参数2以后就是执行函数的参数
- 使用apply方法改变this指向 fn.apply(this(要修改的那个对象),[参数1,参数2])
注: 使用call和apply传入的第一个参数可以是null,表示为函数调用模式,this指向window当第一个参数为值类型的时候,会将值类型转换为对应的对象
包装对象
系统对象也是基于原型的程序 尽量不要去修改或者添加系统对象下面的方法和属性
所有的基本类型都有自己的包装对象: Number String Boolean
基础类型在执行方法或者属性的时候,会找到对应的包装对象1
2
3
4
5
6
7
8
9
10
11
12
13var a = new String('abc') //console.log(typeof a)
// 通过包装对象去执行方法或者属性
a.charAt(0)
// 基本类型的包装对象 只存在于一行代码的执行瞬间 执行完后,包装对象立即被销毁
var str = 'abc'
str.num = 10
console.log(str.num) //undefined
// 基本数据类型: 基于字面量方式创建出来的值是基本类型值 number
// 基于构造函数方式创建出来的值是引用类型 object
var num1 = 12
var num2 = new Number(12)
console.log(typeof num1) // number
console.log(typeof num2) // object
原型和原型链: 实例对象和原型之间的链接 proto
原型里面默认的属性和方法 不能for in打印
原型链的最外层是 Object.prototype
instanceof
检测当前实例是否属于这个类1
2
3
4let arr = []
console.log(arr instanceof Array) // true
console.log(arr instanceof RegExp) // false
console.log(arr instanceof Object) // truein
检测当前对象是否存在某个属性(对象的私有属性或共有属性,只要有结果就是true)1
2
3
4
5
6
7function Fn() {
this.m = 10
}
var f = new Fn()
console.log('m' in f) // true
console.log('n' in f) // false
console.log('toString' in f) // truehasOwnProperty()
检测当前属性是否为对象的私有属性(不仅要有这个属性,还必须是私有的)1
2
3
4
5
6
7function Fn() {
this.m = 10
}
var f = new Fn()
console.log(f.hasOwnProperty('m')) // true
console.log(f.hasOwnProperty('n')) // false
console.log(f.hasOwnProperty('toString')) // false 不是私有属性Object.prototype.hasOwnPeroperty
对象中是否有某属性,返回布尔值
原型如果改成json写法 会影响这个属性constructor
对象.constructor
查看对象的构造函数
构造函数:原型里面默认的属性
每一个函数都会有的,都是自动生成的Aaa.prototype.constructor = Aaa;
原型如果改成json
写法 会影响这个属性原型查找原则
1.当访问一个对象的成员的时候,先在自身找有没有,如果有,直接使用
2.如果没有找到,则去当前对象的原型对象中去找,如果有,直接使用
3.如果没有找到,则去原型对象的原型对象中去找,如果有,直接使用
4.直到Object
,如果还是没有,则返回null
构造函数显式原型prototype上的constructor属性等于构造函数本身
Person.prototype.constructor===Person) //true
- 实例对象的隐式原型等于它构造函数的显示原型
person.__proto__===Person.prototype //true
- es6中操纵原型的内置函数
- Object.create 根据指定的原型创建新对象, 原型课时是null
- Obejct.getPrototypeOf() 获取一个对象的原型
- Object.setPrototypeOf() 设置一个对象的原型
- 构造函数模式用于定义实例属性,而原型模式用于定义共用方法和共享的属性。
1 | //构造函数 |
继承
一个对象没有一些方法和属性,而把另一个对象的属性和方法,拿过来自己用就是继承
- 子对象可以继承父对象
子对象拥有父对象有的东西
子对象可以扩展
子对象的扩展不会影响到父对象 继承的方式
(1) 混入式继承
(2) 原型继承
(3) 经典继承
(4) 原型链继承js对象的默认继承是原型继承
1
2
3function Phone{}
Phone.prototype = new Object() // 默认就会有这一步
Phone.prototype.__proto__ === Object.prototype继承的方式
原型链继承 借用构造函数继承 原型+构造函数继承 寄生式继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73// 1. 原型链继承
function Animal () {
this.age = 20
}
function Cat () {
this.name = 'jack'
}
var cat = new Cat()
console.log(cat.name); // jaack
console.log(cat.age); // undefined
// 让Cat对象拥有了Animal对象的属性和方法
Cat.prototype = new Animal()
var cat = new Cat()
console.log(cat.name); // jaack
console.log(cat.age); // 20
// 2. 借用构造函数继承 在子类构造函数内部调用父类构造函数
function Animal () {
this.age = 20
}
function Cat () {
// Cat的所有对象借用了Animal对象的构造函数 借用构造函数可以传参
// Animal.call(this, '30')
Animal.call(this)
this.name = 'jack'
}
var cat = new Cat()
console.log(cat.name); // jaack
console.log(cat.age); // 20
// 3. 组合继承 原型链 + 借用构造函数继承
// 使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承
function SuperType(name){
this.name = name
this.colors = ['blue', 'green']
}
SuperType.prototype.sayName = function(){
console.log(this.name)
}
function SubType(name, age){
// 继承属性
SuperType.call(this, name)
this.age = age
}
// 继承方法
SubType.prototype = new SuperType()
SubType.prototype.sayAge = function(){
console.log(this.age)
}
var sub = new SubType('tew', 28)
sub.colors.push('red')
console.log(sub.colors) // ["blue", "green", "red"]
sub.sayName() // tew
sub.sayAge() // 28
var sub2 = new SubType('bob', 26)
console.log(sub2.colors) // ["blue", "green"]
sub2.sayName() // bob
sub2.sayAge() // 26
// 4. 寄生式继承
function Person(name, age){
this.name = name
this.age = age
}
function createPerson(name, age){
var obj = {}
Person.call(obj, name, age)
return obj
}
var person = createPerson('tew', 28)
console.log(person) // {name: "tew", age: 28}
console.log(person.constructor) // ƒ Object() { [native code] }