面向过程:每一步都要亲力亲为,每一个步骤都很清楚,注重过程
面向对象:找到合适的对象,让对象完成需求,注重结果
对象
现实的对象:可描述出来的具体事物
描述对象:通过对象的特征和行为来进行描述
代码的对象:现实中的对象的抽象
抽象的过程:将特征抽象为属性,行为抽象为方法
1、创建对象 (增删改)
创建对象的方式
1、字面量方式
2、内置构造函数方式
// 字面量方式
let o = {}
console.log(o); //Object
// 内置构造函数方式
let o1 = new Object()
console.log(o1); //Object
// 对象成员的操作
let obj = {
name: 'blue',
study: function () {
console.log('学习');
console.log(this); //指向obj对象
},
hobby() {
console.log('爱好');
console.log(this); //指向obj对象
}
}
let obj1 = new Object()
// 添加属性age
obj.age = 11
console.log(obj); //{name: 'blue', age: 11, study: ƒ, hobby: ƒ}
// 删除属性name
delete obj.name
console.log(obj); //{age: 11, study: ƒ, hobby: ƒ}
// 修改属性值
obj.name = 'yellow'
console.log(obj.name); //yellow
2、工厂函数
批量创建对象
封装一个函数来创建对象(函数 <===> 工厂函数)
function createObj(name, age) {
// 创建一个空对象
let o = new Object()
// 添加数据
o.name = name
o.age = age
o.study = () => { console.log('学习'); }
// 返回对象
return o
}
let o1 = createObj('blue', 11)
let o2 = createObj('green', 12)
console.log(o1, 'o1'); //{name: 'blue', age: 11, study: ƒ} 'o1'
console.log(o2, 'o2'); //{name: 'green', age: 12, study: ƒ} 'o2'
3、检测数据类型
检测数据类型的方法有三种:typeof、instanceof和Object.prototype.toString.call()
1、typeof:null检测出来的类型是Object,数组和对象无法知道具体谁是谁
2、instanceof:普通数据类型检测有误,只能检测复杂数据类型
3、Object.prototype.toString.call():万能检测数据类型
// typeof 可以检测数据类型
console.log(typeof (100)); //number
console.log(typeof ('hello')); //string
console.log(typeof (true)); //boolean
console.log(typeof (undefined)); //undefined
console.log(typeof (null)); //object
console.log(typeof ([])); //object
console.log(typeof ({})); //object
console.log(typeof (new Date())); //object
// 存在问题:null检测出来的类型是Object,数组和对象无法知道具体谁是谁
// instanceof 可以检测数据类型(返回true或false)
var num = 100
var obj = {}
console.log(num instanceof Number); //false
console.log(obj instanceof Object); //true
// 存在问题:普通数据类型检测有误,只能检测复杂数据类型
// 万能检测数据类型 Object.prototype.toString.call()
console.log(Object.prototype.toString.call(100)); //Number
console.log(Object.prototype.toString.call('hello')); //String
console.log(Object.prototype.toString.call(true)); //[object Boolean]
console.log(Object.prototype.toString.call(undefined)); //Undefined
console.log(Object.prototype.toString.call(null)); //Null
console.log(Object.prototype.toString.call({})); //Object
console.log(Object.prototype.toString.call([])); //Array
console.log(Object.prototype.toString.call(new Date())); //Date
4、构造函数详解
构造函数
面向对象要么直接得到一个对象,要么弄出一个能创造对象的东西
new操作符
new 自动创建一个对象
会把对象赋值给this
返回this
注意:
1、要和new连用
2、首字母大写
3、没有参数可以不带()
4、不要写return
5、构造函数里的this ===> 是本次new赋值的那个实例对象
// 1、普通函数
function Person(a) {
this.name = 'blue'
this.age = a
console.log(a);
console.log(this, 'this'); //谁调用就指向谁
}
// 2、和new连用,就是构造函数
let p1 = new Person(1)
console.log(p1); //Person {name: 'blue'}
let p2 = new Person(2)
console.log(p2); //返回对象Person {name: 'blue'}
// 3、不需传递参数可不写()
let p3 = new Person
console.log(p3); //Person {name: 'blue'}
// 4、this的指向
let p4 = new Person(4) //this指向p4
let p5 = new Person(5) //this指向p5
// 5、构造函数会返回一个对象(如果返回的是普通类型,自动忽视,继续返还this;若返回的是复杂数据类型,强制返回该数据)
function Panda() {
this.age = 11
this.color = '黑白'
this.name = 'hello'
// return this //返回该对象
// return [1, 2, 3] //返回的是[1,2,3]
}
let pan1 = new Panda()
console.log(pan1); //Panda {age: 11, color: '黑白', name: 'hello'}
5、原型
原型__proto__(每个对象都有该属性,该属性指向当前对象的构造函数的原型对象)。
当需要查找对象中的属性或方法时,若对象本身存在,就返回结果;若不存在,就会通过__proto__属性,在当前对象的构造函数的原型对象中找,有就给结果,没有就一直通过__proto__属性去查找上层原型对象,直到null。
每个构造函数都有prototype属性,该属性指向的是原型对象
对象中都有__proto__属性,因此原型对象也有该属性可以指向上层构造函数的原型对象
对象.__proto__和构造函数.prototype指向的是同一个对象空间
原型的出现是为了解决构造函数添加方法的缺点,每次都开辟新的内存空间造成内存浪费
prototype
每个函数身上都会有属性prototype 指向一个原型对象
可通过函数.prototype.复杂数据类型名 = 复杂数据类型值
function Person() {
this.name = 'blue'
}
Person.prototype.age = 11
Person.prototype.sayHi = () => {
console.log('hello');
}
console.dir(Person.prototype);
let p1 = new Person() //实例对象
let p2 = new Person() //实例对象
// 该对象若存在该方法或属性,直接返回结果
// 该对象若不存在该方法或属性,则通过__proto__属性前往构造函数的原型对象中查找,找不到就继续往上一层查找(找不到最后会undefined)
console.log(p1.sayHi); //返回该函数体
console.log(p1.s); //undefined
我们原型有一个链状结构
== 当一个对象我们不知道是谁构造的时候,我们可以把它看成是object的实例对象
== 也就是说,我们的构造函数的prototype的__proto__指向object.Prototype
== 那么这个object.Prototype也是一个对象,他的__proto__指向哪里呢?
== 因为object是js中的顶级构造函数,我们有一句话叫做万物皆对象
== 所以object.prototype就到头了,object.prototype上的__proto__就是null
原型链:从实例对象开始沿着__proto__形成的连式结构就是这个实例对象的原型链
6、constructor
万物皆对象,所有数据类型都可以看成对象,有对象就有构造函数。
对象有__proto__属性指向当前对象的构造函数的原型对象
对象也有一个constructor属性指向当前对象的构造函数
let arr = [1, 2, 3]
console.log(arr.constructor); //指向一个 Array()的函数
// 数组也是对象
/*
对象有__proto__属性指向当前对象的构造函数的原型对象
对象也有一个constructor属性指向当前对象的构造函数
*/
let arr2 = new Array(1, 2, 3)
console.log(arr2); //[1,2,3]
7、ES6的class语法
ES5语法书写构造函数如下:
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayHi = function () {
console.log('hello');
}
let p1 = new Person('blue', 11)
console.log(p1); //对象Person {name: 'blue', age: 11}
ES6语法书写构造函数如下:
class 类名(也叫构造函数名){
constructor(形参1,形参2){}
函数名1(){}
}
class Person1 {
constructor(name, age) {
this.name = name
this.age = age
}
sayHi1(a) {
console.log(a + 'hello');
}
}
let p2 = new Person1('yellow', 12)
p2.sayHi1(2) //2hello
console.log(p2); //Person1 {name: 'yellow', age: 12}