对象
面向过程和面向对象
面向对象和面向过程是两种编程思想。
-
面向过程
过程为中心的编程思想。过程,完成一件事的步骤。
-
面向对象
以对象作为中心的编程思想,对象,可以理解为真真正正存在的东西。
面向对象的优势
-
符合人类的思维习惯。
-
能够适应复杂的需求变化。
核心就是
可扩展性
类和对象
-
类:一组相似事物的统称。
- 一组:就是有多个。
- 相似:比较像,但不完全相同。
-
类的组成:
- 属性:类具有的特性(通常是名词)。
- 方法:类具有的功能(通常是动词)。
-
对象是类的具体化,实物,实体,由类创建出来的。
类是模板,让多个对象拥有共同的属性、方法。
JavaScript中的对象
JavaScript中没有具体的类,直接就是对象。
为什么这样设计:有类无非就是为了复用代码(共同的属性、方法)
数组:有序的键值对。
对象:无序的键值对儿,值可以是基本类型、对象或者函数。
对象声明方式
-
方式一:字面量方式声明
字面量方式的对象是由多个
键:值
对组成的,每个键:值
对之间使用逗号分隔,最后一个不用逗号。对象的属性值也可以是函数,因为函数本身也是一种数据。
注意:
- 键是字符串并且不加引号(加上也行),即使是其他类型也会被转换为字符串。
- 如果键名不符合标识符命名规则就必须加上引号。
-
方式二:Object构造函数创建
new Object
new是操作符标识调用后面的内容(Object,可以暂时将它看成一个类,但Object不是类)创建一个对象。
new后面的Object、Array不是类,实际上是函数,当使用new调用某个函数时可以说是创建了一个xxxx类型
的对象。
new Array()
,创建了一个Array类型的对象。
new Object()
,创建了一个Object类型的对象。
注意:
-
对象字面量表达式法,它的目的是用来检查创建包含大量属性的对象的过程。(内部也会调用
new Obejct()
) -
我们一般声明Object类型的对象时一般使用字面量表示方式。
-
Object类型
的实例是个万能的对象,它可以根据其中的属性、方法,存储任何东西。
对象的基本操作
-
访问对象中的属性
-
使用
.
表示法来进行访问(建议使用) -
使用
[]
表示法访问对象属性。(这里面可以放置变量、表达式)- 不符合标识符命名规则需要使用
[]
来进行访问。 - 既然可以放置表达式那么中括号中可以进行运算(可以放变量)。
如果访问的属性不存在,代码会返回undefined。
- 不符合标识符命名规则需要使用
-
-
增加、修改属性(有就修改,没有就添加)
添加、修改的键名不符合标识符规则只能用中括号添加或修改。
-
删除属性
格式:
delete 对象.属性
var声明的全局变量不能使用delete删除,但是不使用var声明的
所谓的全局变量
可以使用delete删除,因为它只是window对象上面的属性。
工厂模式声明对象
如果以new Object和对象字面量方式来创建对象有啥缺点:在创建多个对象时会产生大量重复的代码。
function createPerson(name,age){
var o = new Object();
o.name = name;
o.age = age;
return o;
}
var zhangSan = createPerson('张三',73);
var liSi = createPerson('李四',84);
console.log(zhangSan);
console.log(liSi);
使用构造函数来创建对象
instanceof 操作符
它里面涉及到原型和原型链的一些东西。首先需要知道__它可以用来检测某个对象是否是某个类型的__
构造函数: 就是普通的函数。但是使用了new 操作符
调用,这个时候有些人称它为构造函数
,但是在JavaScript中不存在所谓的构造函数
,它应该叫函数的构造调用
function Person(){
}
function Dog(){
}
定义所谓的构造函数时函数名一般首字母大写。
使用new操作符操作函数之后将会生成一个对象,这个对象就是所谓的构造函数
这种类型的new person()
生成的就是一个Person类型
的对象。
function Dog(){
this.name = '旺财';
this.cate = '泰迪';
this.woof = function(){
console.log('wawa!');
}
}
var d1 = new Dog();
var d2 = new Dog();
console.log(d1);
console.log(d2);
this关键字__暂时__表示的是调用构造函数时生成的这个对象。
我们可以在定义构造函数时定义形参,构造函数内部使用形参。new的时候传入我们的个性化数据
,让我们有不同的属性值。
总结:由于Object类型的对象是万能的对象,不能识别类型,所以我们使用构造函数来生成对象,我们可以设置对应的属性和方法(引入了this关键字,this暂时先理解为生成的这个对象。)
函数构造调用中的return
构造函数中可以使用return语句,如果return的是基本类型那么return的值将会被忽略。最终得到的还是新创建的这个对象。
如果构造函数中返回的是其他对象
,那么就返回这个对象了。
==
的两边操作数都是对象,用来判断这两个对象是否是同一个内存地址。如果是返回true,否则返回false。
函数既是对象,又是可执行的代码:
- 函数的对象方面它拥有属性和方法。
- 代码块方面,它既可以执行特定的代码(普通函数),又可以用来创建特定类型的对象(函数的构造调用)
- 普通函数,没有return,返回的是undefined。有return返回的是指定的值。
- 函数的构造调用,没有return,返回的是
新生成的对象
。有return,return的值如果是对象类型返回的就是这个对象,如果是基本类型将会把返回的值忽略,返回新生成的对象。
原型
-
函数的prototype属性
每个函数在创建的时候都会创建一个prototype属性,这个属性就是
原型属性
,这个属性中存储的是一个空对象(没有自己定义的东西)原型对象中会有一个属性
constructor
,指向的是拥有这个原型对象的构造函数的引用。prototype属性
,只有在函数被当做构造函数时才有效果,它的作用:由同一个构造函数生成的各个实例(对象)之间共享属性和方法。 -
实例对象(通过函数构造调用新创建出来的对象),
__proto__属性
当调用构造函数创建了一个新的实例之后,该实例内部将包含一个指针,指向构造函数的原型对象。(构造函数的prototype属性)
构造函数中的
prototype属性
和构造函数创建出来的实例的__proto__属性
指向的是同一个对象。如果查询构造函数创建的实例的属性时,本实例中没有那么将会查找本实例对象中的
__proto__
是否有该属性,如果有就使用。在原型中查找值的过程是一次搜索,对原型对象所做的任何修改都能够立即从实例上反映出来。
原型:分为显式原型和隐式原型
- 显式原型:就是构造函数中的prototype属性。
- 隐式原型:就是调用函数生成的实例对象的
__proto__
属性。
原型链
重点、难点。
原型链用来描述对象通过__隐式原型__查找属性值的过程。
function Person(name, sex) {
this.name = name;
this.sex = sex;
}
var p = new Person('张三', 'nan');
总结:实例化对象在查找属性时,先从自身去查找有没有这个属性。如果有,直接使用这个属性的值,如果没有,会继续沿着这个对象的隐式原型对象(__proto__
)继续找(__proto__
对应的是该对象所属的构造函数的prototype属性所指的对象),看这个对象中是否有,如果有就使用,如果还没有再去找隐式原型对象(一直到最后默认是Object的显式原型对象),找到以后看有没有这个属性,如果有就使用,如果没有就返回undefiend(代表已经找到顶了)。
原型对象中的属性,是给构造函数实例化出来的对象服务的,构造函数本身不能用。
Object.prototype属性中还有其他的方法,这些方法是系统默认的,
instanceof 操作符
原理:
- instanceof 操作符第一个变量对象,暂时称为A,第二个变量一般是函数,暂时称为B。
- instanceof的判断规则是:沿着A的
__proto__
这条线来找,同时沿着B的prototype这条线来找,如果两条线能够找到同一个对象,那么就返回true。如果找到最后也找不到最后就返回false。
总结:
- 所有的引用类型的实例和instanceof操作都会返回true。
引用类型的实例 instanceof Object
的时候返回true。 - 基本类型不是对象,所以在使用instanceof操作符时始终会返回false。
-
for…in遍历对象。
for .... in
将可枚举的属性自身和原型链中的属性进行遍历。-
数组、函数都是对象,都可以添加属性,同样添加上属性之后也可以维持本来的功能。
-
是否可遍历:一个对象中有些属性是不可以遍历出来的你可以理解为
一般的时候用不到这个属性,它给保护起来了
for…in可以遍历的自身和原型链中可枚举的属性。
var a = { name:'hello', sex:'1' }; //一次从对象中读取一个属性,并把该属性名赋值给pro。 for (var pro in a) { console.log(pro); }
数组也是对象,也可以使用for…in来进行遍历。
var a = [1,2,3,4,5,6]; for (var v in a) { console.log(a[v]); }
上面从语法上面行的通,但是不用
for...in
遍历数组。因为for...in
不能保证遍历的属性,而数组最重要的特性就是有序
。
-