一, 面向对象
面向过程: 凡事亲力亲为, 每件事的具体过程都要知道, 注重过程
面向对象: 根据需求寻找对象, 所有的事都用对象来做, 注重结果
面向对象特性: 封装, 继承, 多态(抽象性)
js 是一门基于对象的语言: js 不是面向对象的语言, 但是可以模拟面向对象的思想
对象是定义: 有特征和行为, 具体特指某一事物
二, 创建对象的方法
1. 调用系统的构造函数创建对象
- var obj=new Object();// 关键词 Object, 大写首字母
- obj.name="小明";
- obj.age=20;
- obj.sex="男";
- obj.play=function(){
- console.log("我在玩游戏");
- };
- obj.showName=function(){
- console.log("我叫"+this.name)
- }
- console.log(obj.name);// 小明
- console.log(obj.age);//20
- console.log(obj.sex);// 男
- obj.play();// 我在玩游戏
- obj.showName();// 我叫小明
这种方法通过 new 关键字生成一个对象, 然后根据 JavaScript 是动态语言的特性来添加属性和方法, 构造一个对象.
在当前的对象的方法中, 可以使用 this 代替当前对象
这种方法的问题在于: 如果我们需要多次创建对象, 那么就需要重复代码多次, 不利于代码的复用.
2. 工厂模式: 一次性创建多个对象 -- 工厂模式创建对象: 利用函数封装起来, 后面调用
原始版本
- function creatObj(){
- var obj= new Object;
- obj.name="关羽";
- obj.age=30;
- obj.showName=function(){
- console.log("我叫"+this.name);
- };
- obj.showAge=function(){
- console.log("我今年"+this.age);
- };
- return obj;
- }
- var obj1=creatObj();
- var obj2=creatObj();
- obj1.showName();// 我叫关羽
- obj1.showAge();// 我今年 30
- obj2.showName();// 我叫关羽
- obj2.showAge();// 我今年 30
这种方法虽然也实现了创建对象, 但是同样地, 如果需要多次创建对象, 而且属性内容不一样的话, 也是需要重复代码多遍. 需要重新考虑代码重用率, 接下来修改代码, 使其可以提高代码重复率, 而且可以改变工厂方法, 传入参数赋值.
改进版本
- function creatObj(name,age){
- var obj= new Object;
- obj.name=name;
- obj.age=age;
- obj.showName=function(){
- console.log("我叫"+this.name);
- };
- obj.showAge=function(){
- console.log("我今年"+this.age);
- };
- return obj;
- }
- var obj1= new creatObj("刘备",32);
- var obj2= new creatObj("关羽",30);
- obj1.showName();// 我叫刘备
- obj1.showAge();// 我今年 32
- obj2.showName();// 我叫关羽
- obj2.showAge();// 我今年 30
这种方法虽然可以提高代码的重用率, 但和面向对象中类的概念相比, 有一个很大的缺陷.
面向对象强调对象的属性私有, 但对象的方法是共享. 而上面的工厂方法在创建对象时, 要为每个对象创建各自私有的方法.
同时, 由于为每个对象都创建逻辑相同的方法, 所以很浪费内存.
最终版本
- function creatObj(name,age){
- var obj= new Object;
- obj.name=name;
- obj.age=age;
- obj.showName=showName;
- obj.showAge=showAge;
- return obj;
- }
- showName=function(){
- console.log("我叫"+this.name);
- };
- showAge=function(){
- console.log("我今年"+this.age);
- };
- var obj1=new creatObj("刘备",32);
- var obj2=new creatObj("关羽",30);
- obj1.showName();// 我叫刘备
- obj1.showAge();// 我今年 32
- obj2.showName();// 我叫关羽
- obj2.showAge();// 我今年 30
上面通过定义几个函数对象, 解决了不同对象持有函数对象的私有问题. 现在所有对象的方法都持有上面两个函数的引用.
但是这么一来, 对象的函数和对象又相互独立, 这和面向对象中特定方法属于特定类的思想不符合.
3. 自定义构造函数创建对象(结合第一种和需求, 通过工厂模式创建)
- function Person(name,age){
- this.name=name;
- this.age=age;
- this.showName=function(){
- console.log("我叫"+this.name);
- };
- this.showAge=function(){
- console.log("我今年"+this.age);
- };
- };
- var obj1=new Person("刘备","32");
- var obj2=new Person("关羽","30");
- obj1.showName();// 我叫刘备
- obj1.showAge();// 我今年 32
- obj2.showName();// 我叫关羽
- obj2.showAge();// 我今年 30
构造函数的方法和工厂方法一样, 会为每个对象创建独享的函数对象. 当然也可以将这些函数对象定义在构造函数外面, 这样有了对象和方法相互独立的问题.
使用构造函数存在的最大问题就是每个实例都会将所有的属性创建一次. 这个对于数值属性来说可以接受, 但是如果函数方法每个实例都要创建一遍, 则不合理.
自定义构造函数: 没有 var, 没有返回值, 用 this 代替当前对象
要创建 Person()的新实例, 必须使用 new 操作符.
构造函数和函数的区别: 构造函数的名字首字母一般大写
自定义构造函数创建对象做了四件事:
在内存中开辟 (申请) 空间, 存储新的对象
把 this 设置新的对象
设置对象的属性和方法的值
把 this 这个对象返回
4. 字面量创建对象
- var obj={
- name:"刘备",
- age:32,
- height:"180cm"
- }
- console.log(obj.name);// 刘备
- console.log(obj.age);//32
- console.log(obj.height);//180cm
- console.log(obj instanceof Object);//true
字面量创建的对象的缺陷: 一次性的对象
注意属性与属性之间用逗号, 不是分号
三, 一些结论
1. 如何获取该变量 (对象) 是不是属于什么类型?
语法: 变量 instanceof 类型的名字 ------- 布尔类型, 输出是 true 或者 false
类型的名字首字母大写
- var obj={
- name:"张飞",
- age:32,
- };
- console.log(obj instanceof Object);//true
2. 对象是一组有序属性的集合, 属性的值可以是任意的类型
3. 点语法: 没有什么就点什么, 可以设置和获取和获取对象属性
- var obj={
- name:"刘备",
- age:32,
- };
- obj.height="180cm";// 添加 height 属性
- console.log(obj.name);// 刘备
- console.log(obj.age);//32
- console.log(obj.height);//180cm
4. 设置和获取属性的另外一种方法是通过[ " " ], 必须有双引号
- var obj={
- name:"关羽",
- age:"30",
- };
- obj["height"]="190cm";// 添加 height 属性
- console.log(obj["name"]);// 关羽
- console.log(obj["age"]);//30
- console.log(obj["height"]);//190cm
- 5.Json
- var obj={
- "name":"刘备",
- "age":"32",
- "height":"180cm"
- }
json 格式的数据, 一般都是成对的, 键值对的形式
json 也是一个对象, 数据无论是键还是值都是用双引号括起来的
json 不能通过 for 循环遍历, 可以通过 for......in 循环遍历
6. 数据类型
原始数据类型: Number,String,Boolean,undefined,null,Object
基本类型(简单类型, 值类型):Number,String,Boolean
复杂类型(引用类型):Object
空类型: undefined,null
值类型在栈中存储, 引用类型在堆和栈上存储 ----- 对象在堆存储, 对象的地址在栈存储
值类型传递的是值, 引用类型传递的是地址(引用)
- // 例 1:
- var obj={
- name:"李白"
- };
- function f2(obj2){
- obj2.name="韩信";
- }
- console.log(obj.name);// 李白
- f2(obj);
- //obj2.name="韩信"---- 换成 obj.name="韩信"
- console.log(obj.name);// 韩信
- var num=50;
- function f1(num){
- num=60;
- console.log(num);//60
- }
- f1(num);
- //num=60----- 原来的 num=60 没了 换成了 num=50 而且是隐式全局变量
- console.log(num);//50
- // 例 3:
- var num1=55;
- var num2=66;
- function f1(num,num1){
- num=100;
- num1=100;
- num2=100;
- console.log(num);//100
- console.log(num1);//100
- console.log(num2);//100
- }
- f1(num1,num2);
- // num=100;--- 原来的 num 没了 换成了 num1=55, 隐式全局变量
- // num1=100;--- 原来的 num1 没了 换成了 num2=66, 隐式全局变量
- // num2=100;--- 这里对 num2 重新赋值, 变成了 num2=100, 隐式全局变量
- console.log(num1);//55
- console.log(num2);//100
- console.log(num);// 报错
- // 例 4:
- function Person(name,age,salary){
- this.name=name;
- this.age=age;
- this.salary=salary;
- }
- function f1(person){
- person.name="张三";
- person=new Person("李四",18,10);
- }
- var p=new Person("赵六",18,1000);
- console.log(p.name);// 赵六
- f1(p);
- //person.name="张三"----- 换成了 p.name="张三"(代替原来的 "赵六")
- // 下面换成了 p=new Person("李四",18,10)等于新创建了一个对象
- console.log(p.name);// 张三
对象(面向对象, 创建对象方式, Json)
来源: http://www.bubuko.com/infodetail-2574371.html