JS 面向对象

“万物皆对象”。对象是单个事物的抽象;对象是一个容器,封装了属性和方法;属性是对象的状态;方法是对象的行为。
在实际开发中,对象是一个抽象的概念,可以将其简单理解为:数据集或功能集。

一、JavaScript中的对象

面向对象编程——Object Oriented Programming,简称 OOP,是一种编程开发思想。它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。

JavaScript中的编程就是面向对象的编程。而对象就是对生活中对象的一个抽象,是一些无序属性的集合。
其中属性可以包含基本值、对象或函数。对象就是一组没有顺序的值。我们可以把JavaScript中的对象想象成键值对,其中值可以是数据和函数。

二、面向对象基本特性

  1. 封装性:将对象运行所需的资源(方法和数据)封装在程序对象中。也可以理解把客观事物封装成抽象的类。封装可以隐藏实现细节,使得代码模块化。
  2. 继承性:通过继承创建的新类称为“子类”或“派生类”。继承的过程,就是从一般到特殊的过程。继承可以扩展已存在的代码模块(类),提高复用,减少冗余。
  3. 多态性:具体表现为重载和重写。重载就是函数或方法有相同的名称,但参数列表不相同的情形。重写就是子类可继承父类中的方法,而不需要重写编写相同的方法,也可在该方法上做修改。多态可以实现方法的个性化,灵活多变。

三、设计思想

  • 抽象出 Class(构造函数)
  • 根据 Class(构造函数)创建 Instance(实例)
  • 指挥 Instance 得结果

四、创建对象的几种方式

  1. 原始模式: 即对象字面量。
    // 通过对象字面量 创建 一个 对象
    var person = {
    // name 为 属性名;zhangsan 为 属性值
    	name : 'zhangsan',
    	age : 20,
    	sayHi : function () {
    		console.log(this.name + "向你说您好");		
    	}
    };
    // 更改 数据
    person.age = 18;
    // 添加新数据
    person.weight = 120;
    // 删除 数据
    delete person.age;
    
  2. new Object() 创建对象:
    JavaScript 原始提供 Object对象,JavaScript的素有对象都继承自Object对象,即那些对象都是Object的实例。
    Object本身是一个函数,可以当做工具方法使用,将任意值转为对象。此处的 Object() 可以当做构造函数,前面可以使用 new 命令。

new 在这的功能是做了以下事情:

  1. 在内存中创建了一个新的空对象
  2. 会让 this 指向这个新的空对象
  3. 执行构造函数 (目的:给这个新对象加属性和方法)
  4. 会返回这个新对象
    var obj = new Object();
  1. 工厂模式
    如果要创建多个类似的对象,可以将 new Object() 过程封装到一个函数中,将来调用函数就 能创建一个对象,相当于一个生产对象的函数工厂,用来简化代码。
// 创建 函数工厂
function createPerson(name,age) { 
	var obj = new Object;  //或obj = {} 原材料阶段
	obj.name = name;   // 加工
	obj.age = age;  // 加工
	return obj;  // 输出产品
}
// 实例化
var person1 = createPerson("zs","19");
var person2 = createPerson("lisi","20");
  1. 自定义构造函数

在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数。构造函数首字母一般大写,以便于普通函数进行区分。

自定义一个创建具体对象的构造函数,函数内部不需要new一个构造函数的过程,直接使用this代替对象进行属性和方法的书写,不需要return。

function CreatePerson(name,age) {
	//不需要自己创建对象了
	this.name = name;  //添加属性,this指向构造函数的实例对象
	this.age = age;
// 不需要自己 return 了
}
// 实例化
var ps = new CreatePerson("zhangsan","23");
var ps2 = new CreatePerson("lisi", "21");

五、遍历对象

For in 循环。输出每一项的属性名和属性值。
语法:
for(var k in obj) {
console.log(k + “项的属性值是” + obj[k]);
}

六、构造函数的相关内容

1. 构造函数和实例对象的关系

构造函数是根据具体的事物抽象出来的抽象模块。
实例对象是根据抽象的构造函数模块得到的具体实例对象。
每一个实例对象都通过一个 constructor 属性,指向创建该实例的构造函数

2. 静态成员和实例成员

使用构造函数方法创建对象时,可以给构造函数和创建的实例对象添加属性和方法,这些属性和方法都叫做 成员
实例成员:在构造函数内部添加给this 的成员,属于实例对象的成员,在创建实例对象后必须由对象调用。
静态成员:添加给构造函数自身的成员,只能使用构造函数调用,不能使用生成的实例对象调用。

//创建一个构造函数
function Person(name, age) {
// 通过 this 添加的 内部属性,就是 实例成员
	this.name = name;
	this.age = age;
	
	// 构造函数 可能存在的问题
	this.type = "human";
	this.sayName = function () {
		console.log(this.name);
	};
}
// 通过 构造函数自身添加的成员 就是 静态成员
Person.version = "1.0";

// 生成 实例对象
var p = new Person("zhangsan", "24");

 // 判断一个对象的具体对象类型,需要使用 instanceof 进行判断
console.log(p instanceof Person);

从上段代码中可以了解到 Person 这个构造函数中有个 值不变的实例成员和一个 sayName 方法。每实例化一个对象,对象里面都会有这不变的属性和 方法。就会存在一个浪费内存的问题。引入下一个知识点 Prototype 原型。

七、Prototype 原型

JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向构造函数的原型对象。这个原型对象的所有属性和方法,都会被构造函数的实例对象所拥有。因此我们可以把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上。
构造函数上的 prototype对象默认都有一个 constructor属性,指向 prototype对象所在函数。
通过构造函数得到的实例对象内部会包含一个指向构造函数的 prototype 对象的指针 _proto_(原型链)。

构造函数、实例、原型对象三者之间的关系图
关系图

function Person(name, age) {
	this.name = name;
	this.age = age;
}
//方法写在 原型 里面
Person.prototype.sayName = function () {
	console.log(this.name);
}
// 不变的属性 也可以写入 原型里面
Person.type = "human";

//生成 实例对象
var person1 = new Person("zhangsan","25");
var person2 = new Person("lisi","23");

// 这时所有实例的sayName 方法,都是同一个内存地址,指向prototype对象,因此就提高了运行效率。
console.log(person1.sayName === person2.sayName);

八、__proto__ 原型链

constructor是属于构造函数的 原型对象的属性。
所有的对象都有一个__proto__的属性,是一个指针,指向的就是生成实例对象的 构造函数的原型对象 prototype。
__proto__属性并不是一个标准的属性,是浏览器自己根据语法自动生成的,在实际开发过程中,不会书写该属性,

原型链

原型链的查找机制

每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性:

  1. 首先从对象实例本身开始搜索
  2. 如果在实例中找到了具有给定名字的属性,则返回该属性的值。
  3. 如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性
  4. 如果原型对象中找到了这个属性,则返回该属性的值。
原型对象使用的建议

在定义构造函数时,可以根据成员的功能不同,分别进行设置。

  • 私有成员(一般就是非函数成员)放到构造函数中
  • 共享成员(一般就是函数)放到原型对象中
  • 如果重置了 prototype ,记得手动将 constructor 的指向正确的构造函数。
function Person(name , age ) {
	// 私有成员
	this.name = name;
	this.age = age;
}

// 公共成员
// 重置 直接使用一个对象字面量对 原型对象进行赋值
Person.prototype = {
	constructor : Person,  // 需要手动 将 constructor 属性指向正确的构造函数
    type : "human",
    sayName : function () {
        console.log(this.name);
    }
}
// 生成实例对象
var person1 = new Person("zhangsan","14");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值