1
0
mirror of https://github.com/Daotin/Web.git synced 2024-10-30 04:24:45 +08:00
Web-main/03-JS基础/08-面向对象.md
2018-11-19 19:22:56 +08:00

289 lines
8.0 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 一、面向对象
## 1、对象创建方式
### 1.1、调用系统函数创建对象
**(创建对象的最简单方式就是创建一个 Object 的实例,然后再为它添加属性和方法。)**
```javascript
var obj = new Object();
obj.name = "Daotin";
obj.age = 18;
obj.eat = function () {
  console.log("我很能吃");
);
```
缺点:使用同一个接口创建很多对象,会产生大量的重复代码。
### 1.2、自定义构造函数创建对象
**工厂模式创建对象**:考虑到在 ECMAScript 中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节(把创建一个函数的过程封装在一个函数里面),**缺点:创建的对象属性都是一样的。**
```javascript
function creatObject() {
var obj = new Object();
obj.name = "Daotin";
obj.age = 18;
obj.eat = function () {
console.log("我很能吃");
};
return obj;
}
var person = creatObject();
person.eat();
```
**工厂模式创建对象进阶版:**可以修改属性
```javascript
function creatObject(name, age) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.eat = function () {
console.log("我很能吃");
};
return obj;
}java
var person = creatObject("Daotin", 18);
person.eat();
```
**自定义构造函数:**(函数和构造函数的区别:没有区别,但是通常构造函数**首字母大写**
**特点:**
- 没有显式地创建对象;
- 直接将属性和方法赋给了 this 对象;
- 没有 return 语句。
```javascript
function CreatObject() { // 首字母大写
this.name = "Daotin";
this.age = 18;
this.eat = function () {
console.log("我很能吃");
};
}
var person = new CreatObject();
person.eat();
```
**进阶(传参数):**
```javascript
function CreatObject(name, age) {
this.name = name;
this.age = age;
this.eat = function () {
console.log("我很能吃");
};
}
var person = new CreatObject();
person.eat();
```
**构造函数的问题**
构造函数模式虽然好用,但也并非没有缺点。使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。在前面的例子中, person1 和 person2 都有一个名为 sayName()的方法,但那两个方法不是同一个 Function 的实例。不要忘了——ECMAScript 中的函数是对象,因此每定义一个函数,也就是实例化了一个对象。从逻辑角度讲,此时的构造函数也可以这样义。
```javascript
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = new Function("alert(this.name)"); // 与声明函数在逻辑上是等价的
}
```
从这个角度上来看构造函数,更容易明白每个 Person 实例都包含一个不同的 Function 实例(以显示 name 属性)的本质。说明白些,以这种方式创建函数,会导致不同的作用域链和标识符解析,但创建 Function 新实例的机制仍然是相同的。因此,不同实例上的同名函数是不相等的,以下代码可以证明这一点:` alert(person1.sayName == person2.sayName); //false `
然而,创建两个完成同样任务的 Function 实例的确没有必要;况且有 this 对象在,根本不用在执行代码前就把函数绑定到特定对象上面。因此,大可像下面这样,通过**把函数定义转移到构造函数外部来解决这个问题。**
```javascript
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName(){
alert(this.name);
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
```
在这个例子中,我们把 sayName() 函数的定义转移到了构造函数外部。而在构造函数内部,我们将 sayName 属性设置成等于全局的 sayName 函数。这样一来,由于 sayName 包含的是一个指向函数的指针,因此 person1 和 person2 对象就共享了在全局作用域中定义的同一个 sayName() 函数。
### 1.3、使用对象字面量表示法
对象字面量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程。
如果留空其花括号,则可以定义只包含默认属性和方法的对象 `var person = {}; //与 new Object()相同 `
**缺点:一次性对象,无法修改属性的值。**
```javascript
var obj = {
name:"Daotin", // 注意是属性赋值是冒号
age: 18,
eat: function () {
console.log("我很能吃");
} // 最后一个后面没有逗号
};
obj.eat();
```
## 2、访问对象属性
**点表示法 和 方括号表示法**
```javascript
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"
```
从功能上看,这两种访问对象属性的方法没有任何区别。但方括号语法的主要优点是可以通过变量来访问属性(属性绑定),例如:
```javascript
var propertyName = "name";
alert(person[propertyName]); //"Nicholas"
```
**如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括号表示法。**
例如:` person["first name"] = "Nicholas"; `
由于"first name"中包含一个空格,所以不能使用点表示法来访问它。然而,属性名中是可以包含非字母非数字的,这时候就可以使用方括号表示法来访问它们。通常,除非必须使用变量来访问属性,否则我们建议使用点表示法。
**PS 如果访问一个没有的属性的值,那么这个值为 undefined而不是报错**
因为 js 是一门动态类型的语言,不管使用点表示法还是方括号表示法,如果没有这个属性,就相当于在创建这个属性,然而这个时候没有赋值,所以就是 undefined。
## 3、访问对象方法
```javascript
对象名.函数名();
```
## 4、JSON
**什么是JSON**
JSON 的全称为:**JavaScript Object Notation**JavaScript对象表示形式就是对象字面量
JSON格式的数据一般都是成对的键值对。
**JSON和对象字面量的区别**
json 和对象对象字面量的区别仅仅在于json 格式的数据中的键必须用双引号括起来;
```javascript
var json = {
"name" : "zs",
"age" : 18,
"sex" : true,
"sayHi" : function() {
console.log(this.name);
}
};
```
##5、字面量的遍历
**对象本身没有 length所以不能用 for 循环遍历。要使用 for...in...**
```javascript
var json = {aaa: 1, bbb: 2, ccc: 3, ddd: 4}
for(var key in json){
//key代表aaa,bbb.....等
//json[key]代表1,2,3....等k 不要加引号)
}
```
##6、值传递和引用类型传递
**分析值传递和址传递最好的方法就是画图分析,最简单。**
##7、内置对象
`Math, Date, String, Array `
学习的时候可以查阅在线文档:
[MDN 在线文档](https://developer.mozilla.org/zh-CN/)
[菜鸟教程](http://www.runoob.com/)
##8、基本包装类型
本身是基本类型,但是在执行的过程中,如果这种类型的变量调用了属性或者方法,那么这种类型就不是基本类型了,而是基本包装类型。这个变量也不是普通变量了,而是基本包装类型的变量。
```javascript
var str = "hello";
str = str.replace("he", "wo");
console.log(str); // wollo
```
**需要注意的地方:**
如果一个`对象&&true`那么结果是true
如果一个`true&&对象`,那么结果是对象。
```javascript
var flag = new Boolean(false);
var result = flag && true;
var result1 = true && flag;
console.log(result); // true
console.log(result1); // Boolean
```
```javascript
var num = 10; // 基本类型
var num2 = Number("10"); // 不是基本包装类型,而是转换,这里换成 Boolean 也成立
var num3 = new Number("10"); // 这才是基本包装类型
```