1.面向对象的相关概念:
1.对象指的是具体的事物。
eg:电脑,人等不是对象。具体的某个电脑,某个人才是对象。
2.对象的定义:
键值对的集合|属性(方法)的工具包|对变量和函数的封装。
3.面向对象的三大特性:封装、继承、多态。
js的封装:使用对象来封装变量和函数。
js的继承:js没有类的概念。
js的继承是一个对象获得另外一个对象的属性和方法的行为。
4.创建对象的方式:
- 字面量
- 内置构造函数(new Object())
- 简单工厂函数创建
- 自定义构造函数
- Object.create()
/**
* 字面量方式
*/
var book1 = {
name:'西游记',
author:'罗贯中',
price:'20',
desLog:function(){
console.log("书名:"+this.name +" 作者:"+this.author);
}
}
/**
* 内置对象构造函数
*/
var book = new Object();
book.name = "红楼梦";
book.author = "曹雪芹";
book.price = "30";
book.desLog = function(){
console.log("书名:"+this.name +" 作者:"+this.author);
}
book.desLog();
前两种方式存在的问题:若创建多个同类型的对象,字面量方式和内置构造函数方式中代码的冗余度太高,复用性比较差。
/**
* 简单工厂函数创建
*/
function createBook(name,author,price){
var book = new Object();
book.name = name;
book.author = author;
book.price = price;
book.desLog = function(){
console.log("书名:"+this.name +" 作者:"+this.author);
}
//此处一定要返回该对象
return book;
}
function Painting(name,author,price){
var paint = new Object();
paint.name = name;
paint.author = author;
paint.price = price;
paint.desLog = function(){
console.log("书名:"+this.name +" 作者:"+this.author);
}
//此处一定要返回该对象
return paint;
}
var book3 = createBook("西游记","罗贯中","20");
var book4 = Painting("向日葵","梵高","3000000");
//无法区分对象的类型 书?画
简单工厂函数虽然可以解决冗余度问题,若存在几个相似类型对象时,无法区分对象的类型。
function Person(name,age){
this.name = name;
this.age = age;
this.setName = function(){
console.log(this.name);
}
}
var p1 = new Person("张三","20");
var p2 = new Person("李四","10");
p1.setName();
p2.setName();
console.log(p1.setName == p2.setName); //false
自定义构造函数可以将对象的类型区分开,但是构造函数必须要和new一起使用,如果直接调用则无法创建对象。 当声明两个相同的对象,这两个对象访问同一个方法是,该方法会各被调用一次。
若需要让多个对象共享同一个函数,考虑到把函数抽取到构造函数外部,此时又会破坏代码的封装性。
自定义构造函数创建对象的内部实现过程:
1.提供构造函数
2.通过new创造一个空的对象:object
3.设置新创建对象的原型对象为构造函数的原型对象
4.设置新创建对象的构造函数为当前的构造函数
5.把新创建的对象赋值给this
6.通过this设置属性和方法
7.默认在最后把新创建的对象返回
(若有显示的return,
返回值为值类型,忽略该值,返回新对象;
返回值为引用类型,return的对象会把新创建的对象覆盖。
)
/*自定义构造函数创建对象的内部实现过程:
*/
function Person(name,age){
//2创建对象,指向Object的一个空对象
// var o = new Object();
//3.设置新创建对象的原型对象为构造函数的原型对象
// o.__proto__ = Person.prototype;
//4.设置新创建对象的构造函数为当前的构造函数
// o.constructor = Person;
//5.把新的对象赋值给this
// this = o;
this.name = name;
this.age = age;
this.setName = function(){
console.log(this.name);
}
//7.默认把新创建的对象返回
// return this;
}
5.区分对象的类型:
instanceof:检查某个对象是否是指定构造函数的实例对象(是不是它创建的对象)。返回值为Boolean
constructor(构造器属性):判断对象是什么类型;返回值:构造函数()
6.构造函数的注意事项:
1.构造函数必须要和new一起使用,如果直接调用则无法创建对象。
2.this的指向:
如果使用new 构造函数()调用, this->具体的对象
如果以普通函数的方式调用, this->window
7.原型对象:
1.构造函数有一个默认的相关联的对象,这个对象就是该构造函数的原型对象。
在使用new 构造函数()创建对象的时候,内部默认会关联这个新对象的原型对象为当前构造函数的原型对象。
原型对象默认是一个空的对象。
2.原型对象的特点(作用):
构造函数的原型对象上面的属性和方法 可以被使用该构造函数创建出来的所有对象所共享。
3.访问原型对象:
①构造函数.prototype
②对象.__proto__
③Object.getPrototype(对象)
4.原型对象的使用:
使用对象的动态特性;
使用字面量的方式直接替换原型对象。
建议:一般把属性写在对象上面,把方法写在原型上面。
5.替换原型对象:
-
注意设置原型对象的位置:
建议在设置完原型对象之后,再统一的创建对象。
constructor指向的是创建当前对象的构造函数。
-
替换了原型对象之后constructor指向Object,所以需要修正构造器属性。
对象本身并没有constructor属性,该属性是原型对象的属性。
6.原型对象使用的注意点:
- 访问属性|方法:
访问逻辑:首先在对象自身找,若没有,再查找原型对象。
设置属性和方法:
1.通过“对象.属性”的方式设置的是实例对象的属性。
实例对象只能在自身上设置属性。
2.设置对象时,如果是引用类型,设置原型对象的属性 通过“对象.属性.属性”。
也就是说:实例对象不能直接在原型对象中设置属性,要想设置原型对象中的属性,要先调用原型对象。
8.prototype和__proto__
的概念
prototype:函数的一个属性。(每个函数都有一个prototype属性。)prototype指向对象。显示修改对象的原型的属性。
__proto__
:一个对象拥有的内置属性。是js内部使用寻找原型链的属性。
9.in关键字和hasOwnProperty属性:
hasOwnProperty:查找自己是否有这个属性(只检查实例成员);
in:遍历对象;判断对象中是否存在指定的属性。(实例成员+原型成员)。
10.isPrototypeOf和Object.getPrototypeOf的区别:
isPrototypeof:判断是否是某个对象的原型对象;
Object.getPrototypeOf(对象):获取原型对象