第一百零九节,JavaScript面向对象与原型

JavaScript面向对象与原型

学习要点:

1.学习条件

2.创建对象

3.原型

4.继承

ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP)。面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是,ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。

 

一.学习条件

在JavaScript视频课程第一节课,就已经声明过,JavaScript课程需要大量的基础。这里,我们再详细探讨一下:

1.xhtml基础:JavaScript方方面面需要用到。

2.扣代码基础:比如XHTML,ASP,PHP课程中的项目都有JS扣代码的过程。

3.面向对象基础:JS的面向对象是非正统且怪异的,必须有正统面向对象基础。

4.以上三大基础,必须是基于项目中掌握的基础,只是学习基础知识不够牢固,必须在项目中掌握上面的基础即可。

二.创建对象

创建一个对象,然后给这个对象新建属性和方法。

var box = new Object();                    //创建一个Object对象
box.name = ‘Lee‘;                        //创建一个name属性并赋值
box.age = 100;                            //创建一个age属性并赋值
box.run = function () {                    //创建一个run()方法并返回值
    return this.name + this.age + ‘运行中...‘;
};
alert(box.run());                        //输出方法的值
alert(box.name);                        //输出属性

上面创建了一个对象,并且创建属性和方法,在run()方法里的this,就是代表box对象本身。这种是JavaScript创建对象最基本的方法,但有个缺点,想创建一个类似的对象,就会产生大量的代码。

var box = new Object();                    //创建一个Object对象
box.name = ‘Lee‘;                        //创建一个name属性并赋值
box.age = 100;                            //创建一个age属性并赋值
box.run = function () {                    //创建一个run()方法并返回值
    return this.name + this.age + ‘运行中...‘;
};
alert(box.run());                        //输出方法的值
alert(box.name);                        //输出属性

var box2 = box;                        //得到box的引用
box2.name = ‘Jack‘;                        //直接改变了name属性
alert(box2.run());                        //用box.run()发现name也改变了

var box2 = new Object();
box2.name = ‘Jack‘;
box2.age = 200;
box2.run = function () {
    return this.name + this.age + ‘运行中...‘;
};
alert(box2.run());                        //这样才避免和box混淆,从而保持独立

工厂模式创建对象【推荐】

为了解决多个类似对象声明的问题,我们可以使用一种叫做工厂模式的方法,这种方法就是为了解决实例化对象产生大量重复的问题。

function createObject(name, age) {        //集中实例化的函数
    var obj = new Object();        //创建一个对象
    obj.name = name;               //追加一个属性
    obj.age = age;                  //追加一个属性
    obj.run = function () {        //追加一个方法
        return this.name + this.age + ‘运行中...‘;   //在对象里面的this代表对象本身,对象里的name属性加上age属性
    };
    return obj;    //返回对象
}

var box1 = createObject(‘Lee‘, 100);        //第一个实例
var box2 = createObject(‘Jack‘, 200);        //第二个实例
alert(box1.run());
alert(box2.run());                        //保持独立
//以后要构造不同数据的实例,只需要构造一个实例传入不同参数即可,这样减少了大量重复代码

工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。所以就有了构造函数

构造函数(构造方法)创建对象【重点推荐】

ECMAScript中可以采用构造函数(构造方法)可用来创建特定的对象。类型于Object对象。

function Box(name, age) {                //构造函数模式创建对象
    this.name = name;             //构造函数后台会自动new Object()创建对象;数体内的this就代表new Object()出来的对象。
    this.age = age;               //向对象追加属性
    this.run = function () {     //向对象追加方法
        return this.name + this.age + ‘运行中...‘;
    };
}

var box1 = new Box(‘Lee‘, 100);            //注意:构造函数对象实列化必须使用new 运算符,构造函数传参初始化对象数据
var box2 = new Box(‘Jack‘, 200);       //构造函数传参初始化对象数据
alert(box1.run());                     //打印box1对象实列化下的run()方法,
alert(box1 instanceof Box);                //很清晰的识别他从属于Box

使用构造函数的方法,即解决了重复实例化的问题,又解决了对象识别的问题,但问题是,这里并没有new Object(),为什么可以实例化Box(),这个是哪里来的呢?

使用了构造函数的方法,和使用工厂模式的方法他们不同之处如下:

1.构造函数方法没有显示的创建对象(new Object());

2.直接将属性和方法赋值给this对象;

3.没有renturn语句。

构造函数的方法有一些规范:

1.函数名和实例化构造名相同且大写,(PS:非强制,但这么写有助于区分构造函数和普通函数);

2.通过构造函数创建对象,必须使用new运算符。

既然通过构造函数可以创建对象,那么这个对象是哪里来的,new Object()在什么地方执行了?执行的过程如下:

1.当使用了构造函数,并且new 构造函数(),那么就后台执行了new Object();

2.将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。

3.执行构造函数内的代码;

4.返回新对象(后台直接返回)。

this关于this的使用

关于this的使用,this其实就是代表当前作用域对象的引用。如果在全局范围this就代表window对象,如果在构造函数体内,就代表当前的构造函数所声明的对象。如果是在对象内,就代表当前对象

var box = 2;
alert(this.box);                            //全局,代表window

构造函数和普通函数的唯一区别,就是他们调用的方式不同。只不过,构造函数也是函数,必须用new运算符来调用,否则就是普通函数。

function Box(name, age) {                //构造函数模式创建对象
    this.name = name;             //构造函数后台会自动new Object()创建对象;数体内的this就代表new Object()出来的对象。
    this.age = age;               //向对象追加属性
    this.run = function () {     //向对象追加方法
        return this.name + this.age + ‘运行中...‘;
    };
}

var box1 = new Box(‘Lee‘, 100);            //注意:构造函数对象实列化必须使用new 运算符,构造函数传参初始化对象数据
var box2 = new Box(‘Jack‘, 200);       //构造函数传参初始化对象数据
alert(box1.run());                     //打印box1对象实列化下的run()方法,

var box3 = new Box(‘Lee‘, 100);            //构造模式调用
alert(box3.run());                      //打印box3对象实列化下的run()方法,

Box(‘Lee‘, 20);                            //普通模式调用,无效

var o = new Object();        //创建一个对象
Box.call(o, ‘林贵秀‘, 200);                    //o对象冒充Box构造函数调用
alert(o.run());           //打印Box构造函数里的run()方法

探讨构造函数内部的方法(或函数)的问题,首先看下两个实例化后的属性或方法是否相等。

function Box(name, age) {                //构造函数模式创建对象
    this.name = name;             //构造函数后台会自动new Object()创建对象;数体内的this就代表new Object()出来的对象。
    this.age = age;               //向对象追加属性
    this.run = function () {     //向对象追加方法
        return this.name + this.age + ‘运行中...‘;
    };
}

var box1 = new Box(‘Lee‘, 100);            //注意:构造函数对象实列化必须使用new 运算符,构造函数传参初始化对象数据
var box2 = new Box(‘Lee‘, 100);       //构造函数传参初始化对象数据

alert(box1.name == box2.name);            //true,属性的值相等
alert(box1.run == box2.run);                //false,方法其实也是一种引用地址
alert(box1.run() == box2.run());            //true,方法的值相等,因为传参一致

可以把构造函数里的方法(或函数)用new Function()方法来代替,得到一样的效果,更加证明,他们最终判断的是引用地址,唯一性。

function Box(name, age) {                //new Function()唯一性
    this.name = name;
    this.age = age;
    this.run = new Function("return this.name + this.age + ‘运行中...‘");
}

我们可以通过构造函数外面绑定同一个函数的方法来保证引用地址的一致性,但这种做法没什么必要,只是加深学习了解:

function Box(name, age) {
    this.name = name;
    this.age = age;
    this.run = run;
}

function run() {                        //通过外面调用,保证引用地址一致
    return this.name + this.age + ‘运行中...‘;
}

虽然使用了全局的函数run()来解决了保证引用地址一致的问题,但这种方式又带来了一个新的问题,全局中的this在对象调用的时候是Box本身,而当作普通函数调用的时候,this又代表window。

三.原型

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。逻辑上可以这么理解:prototype通过调用构造函数而创建的那个对象的原型对象。使用原型的好处可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。

时间: 2024-10-10 09:56:31

第一百零九节,JavaScript面向对象与原型的相关文章

第一百零六节,JavaScript变量作用域及内存

JavaScript变量作用域及内存 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别.JavaScript变量是松散型的(不强制类型)本质,决定了它只是在特定时间用于保存特定值的一个名字而已.由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变. 一.变量及作用域 1.基本类型和引用类型的值 ECMAScript变量可能包含两种不同的数据类型的值:基本类型值和引用类型值.基本类型值指的是那些保存在栈

第一百零一节,JavaScript流程控制语句

JavaScript流程控制语句 学习要点: 1.语句的定义 2.if 语句 3.switch语句 4.do...while语句 5.while语句 6.for语句 7.for...in语句 8.break和continue语句 9.with语句 ECMA-262规定了一组流程控制语句.语句定义了ECMAScript中的主要语法,语句通常由一个或者多个关键字来完成给定的任务.诸如:判断.循环.退出等 一.语句的定义  在ECMAScript中,所有的代码都是由语句来构成的.语句表明执行过程中的流

第一百零三节,JavaScript对象和数组

JavaScript对象和数组 学习要点: 1.Object类型 2.Array类型 3.对象中的方法 什么是对象,其实就是一种类型,即引用类型.而对象的值就是引用类型的实例.在ECMAScript中引用类型是一种数据结构,用于将数据和功能组织在一起.它也常被称做为类,但ECMAScript中却没有这种东西.虽然ECMAScript是一门面向对象的语言,却不具备传统面向对象语言所支持的类和接口等基本结构. 一.Object对象类型 Object类型对象, 到目前为止,我们使用的引用类型最多的可能

第二百零九节,jQuery EasyUI,Pagination(分页)组件

jQuery EasyUI,Pagination(分页)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 Pagination(分页)组件的使用方法,这个组件依赖于 LinkButton(按钮)组件.

第三百零二节,三层架构讲解

第三百零二节,三层架构讲解 三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:表现层(Presentation layer).业务逻辑层(Business Logic Layer).数据访问层(Data access layer).区分层次的目的即为了"高内聚低耦合"的思想.在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构.微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层.业务逻辑层(又或称为领域层).表示层.

“全栈2019”Java第一百零二章:哪些作用域可以声明局部内部类?

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第一百零二章:哪些作用域可以声明局部内部类? 下一章 "全栈2019"Java第一百零三章:匿名内部类详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Java学

“全栈2019”Java第一百零四章:匿名内部类与外部成员互访详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第一百零四章:匿名内部类与外部成员互访详解 下一章 "全栈2019"Java第一百零五章:匿名内部类覆盖作用域成员详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"

“全栈2019”Java第一百零五章:匿名内部类覆盖作用域成员详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第一百零五章:匿名内部类覆盖作用域成员详解 下一章 "全栈2019"Java第一百零六章:匿名内部类与抽象类接口注意事项 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复&quo

“全栈2019”Java第一百零六章:匿名内部类与抽象类接口注意事项

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第一百零六章:匿名内部类与抽象类接口注意事项 下一章 "全栈2019"Java第一百零七章:匿名内部类与构造方法注意事项 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复&quo