主要内容:
1、创建对象的几种方式
2、JavaScript内置对象
3、JavaScript错误--Throw、Try 和 Catch
4、JavaScript 表单验证
一、创建对象的几种方式
1、使用Object或者对象字面变量创建对象
(1)使用Object创建对象
例如:
var student = new Object(); student.name = "cc"; student.age = 20; 这样,一个student对象就创建完毕,拥有2个属性name以及age,分别赋值为“cc ”和20。
(2)使用对象字面量创建对象
例如:
var student = { name:"cc"; age:20 };
但这样有一个问题就冒出来了,如果我们有成百上千个同样的类,student1、student2等等,
我们就不得不重复修改成百上千次。。。不禁泪流满面。。。
那么能不能向工厂车间一样,有一个车床就不断生产处对象呢?所以我们有利器--“工厂模式”!
2、工厂模式创建对象
注意:JavaScript没有类的概念,我们可以使用一种函数将以上对象创建过程封装起来
便于重复调用,同时给出特定接口来初始化对象。
例如:
function createStudent(name,age){ var obj = new Object(); obj.name = name; obj.age = age; return obj; } var stu1 = createStudent("cc1",20); var stu2 = createStudent("cc2",21); var stu3 = createStudent("cc3",22);
如此一来,我们就可以通过createStudent函数源源不断地“生产”对象了。看起来,已经非常
完美了,但贪婪的人类总是不满足的,我们不仅希望“产品”的生产可以像工厂车间一般源源不断,
我们还想知道生产的产品是哪一种类型的。
比如:我们又定义了生产水果对象的createFruit()函数
function createFruit(name,color){ var obj = new.object(); obj.name = name; obj.color = color; return obj; } var stu = createStudent("jack",24); var fruit = createFruit("apple",red);
注意:
对于对象stu,fruit,我们用instanceof操作符去检测,他们统统都是Object类型。
而我们希望知道s1是Student类型的,f1是Fruit类型的、为此,我们还得继续寻找,
用自定义构造函数的方法来创建对象。
3、构造函数模式创建对象(推荐)
在上面创建Object这样的原生对象时,我们就已经使用过构造函数了:
var obj = new Object();
在创建原生数组Array类型对象时,也是用过其构造函数:
var arr = new Array(10); // 构造一个初始长度为10的数组对象
(1)注意:
1、实际上并不存在创建构造函数的特殊语法,其与普通函数唯一的区别在于调用方法。对于任意函数, 使用new操作符调用,那么它就是构造函数;不使用new操作符调用,那么它就是普通函数。 2、按照惯例,我们约定构造函数名以大写字母开头,普通函数以小写字母开头,这样有利于显性区分二者。 例如上面的new Array(),new Object()。
(2)使用new操作符调用构造函数时,会经历4个阶段:
阶段1:创建一个新对象,如:
var a = new Object(name,age); 阶段2:将构造函数作用域赋给新对象(使this指向新对象),如: this.name =name; 阶段3:执行构造函数代码; 阶段4:返回新对象。
(3)了解构造函数和普通函数的区别后,我们使用构造将工厂模式的函数重写,并添加一个方法属性:
// 学生信息的构造函数 function Student(name,age){ this.name = name; this.age = age; this.alertName = function(){ alert(this.name) }; } // 水果的构造函数 function Fruit(name,color){ this.name = name; this.color = color; this.alertName = function(){ alert(this.name) } ; }
接着我们在创建Student和Fruit的对象
var s1 = new Student("cc",21); var f1 = new Fruit("apple","red");
(4)我们使用 instanof 操作符去检测
alert(s1 instanceof Student) // true alert(f1 instanceof Student) // false alert(s1 instanceof Fruit ) // false alert(f1 instanceof Fruit) // true alert(s1 instanceof Object); //true 任何对象均继承自Object alert(f1 instanceof Object); //true 任何对象均继承自Object
(5)构造函数的优化
我们会发现Student和Fruit对象中共有同样的方法,当我们进行调用的时候这无疑是内存的消耗
我们完全可以在执行该函数的时候再这样做,办法是将对象方法移到构造函数外部:
function Student(name,age){ this.name = name; this.age = age; this.callName = callName; } function callName(){ alert(this.name); }
调用方式不变,仍然是创建对象,再调用。不同在于,在调用s1.alert()时,this对象才被绑定到s1上。
var s1 = new Student("cc",21); var s2 = new Student("ss",22);
我们通过将callName()函数定义为全局函数,这样对象中的callName属性则被设置为指向该全局函数的指针。
由此stu1和stu2共享了该全局函数,解决了内存浪费的问题。
但是,又有问题来了?
通过全局函数的方式解决对象内部共享的问题,终究不像一个好的解决方法。如果这样定义的全局函数多了,
我们想要将自定义对象封装的初衷便几乎无法实现了。更好的方案是通过原型对象模式来解决。
4、原型的模式创建对象
原型链甚至原型继承,是整个JS中最难的一部分也是最不好理解的一部分,我也不太理解,很难说清楚,
下面给一个实例帮助大家来了解,更多内容可以去W3C的官网http://www.w3school.com.cn/index.html
实例如下:
function Student() { this.name = 'cc'; this.age = 20; } Student.prototype.alertName = function(){ alert(this.name); }; var stu1 = new Student(); var stu2 = new Student(); stu1.alertName(); //cc stu2.alertName(); //cc alert(stu1.alertName == stu2.alertName); //true 二者共享同一函数
未完待续。。。