函数 js中的函数比较奇怪,不像C中,函数是最小的编译单元,也是实现一个功能的模块。js中,函数是Function类的一个实例,Function这个类有属性,有方法。这就意味着函数可以当作值参数传递。
函数
js中的函数比较奇怪,不像C中,函数是最小的编译单元,也是实现一个功能的模块。js中,函数是Function类的一个实例,Function这个类有属性,有方法。这就意味着函数可以当作值参数传递。
1. 函数的声明方式
// 第一种方式 :定义式的声明 var show = new Function('varg1','varg2','alert(varg1 + varg2)') show(10,20) // 调用这个函数 // 第二种方式 函数是一个值。 var show1 = function (varg1, varg2) { alert(varg1 - varg2) }// 函数是引用类型,因此可以被变量show1引用 show1(20,10) // 第三种方式 function show3(var1,var2){ alert(var1 + var2) }
2.创建对象
// 第一种方法: 普通的对象属性的方式 var p1 = new Object() p1.name = 'zhangsan'//属性 p1.age = 34//属性 p1.say = function say(argument) {// 方法 alert(this.name+this.age) } // 第二种方式:json方式 p2 = { name:'meidong', age:40, say:function say(argument) { alert(this.name+this.age) } }
优点:创建方式灵活,简单容易。
缺点:类模版无发被重复利用,使用工厂模式创建对象,类模版则可重用。
工厂模式创建对象:
function Child(name,age) { var p1 = new Object()// 无发检测类型 p1.name = name p1.age = age p1.say = function say(argument) { alert(this.name+this.age) } return p1 } var c1 = new Child('haha',5); alert(typeof c1)// Object类型
优点:类可从用 。缺点:其它类的类型都是Object,类的类型无发检测。解决方法:使用构造函数可解决这个问题
构造函数创建对象:
function Person(name,age) {// this.age = age this.name = name this.say = function say() { alert(this.name+this.age) } }// 可以重用了,可以监测类型。缺点是,方法占用内存空间 var p4 = new Person('maliu',45) alert(p4 instanceof Person)// ture var p3 = new Person('wangwu',20) alert(p3.say==p4.say)// faulse
优点:可以检测到是Person类型。缺点:类中的方法非常多的是,初始化一个类的实例,每个方法都会占用内存空间。解决方法:把对象的方法,写成全局变量
function say() {// 全局变量 alert(this.name+','+this.age) } function Person(name,age) {// this.age = age this.name = name this.say = say }
优点:节省了对象创建是占用的内存。缺点:在window中可以随意调用。最好是封装在类中。这样的话就用到函数原型了
用函数原型封装类:
function Person() { }// 类中包含一个property属性,指向函数原型对象。而且所有对象实例共享原型对象的属性和方法。 var p1 = new Person()// 创建一个对象实例。 Person.prototype.name = 'leon' Person.prototype.age = 32 Person.prototype.friend = ['meidong','mark'] Person.prototype.constructor = Person Person.prototype.say = function say() { alert(this.name+','+this.age) } p1.say() //leon,32 p1.friend.push('mattt') var p2 = new Person() p2.say() //leon,32 alert(p1.say == p2.say)// ture alert(p1.friend)// ['meidong','mark','mattt'] alert(p2.friend)// ['meidong','mark','mattt']p2中也push到了mattt,这两个访问同一块内存,因为是引用类型去访问都函数的原型 say()// 报错,not find function
优点:获得了面向对象的封装特性 缺点:无发通过构造函数初始化属性,当属性引用类型,会造成变量重复。解决方法是 使用构造方法
function Child(name,age,friend) { this.name = name this.age = age this.friend = friend if (self.say != 'function') {//使用到会创建。 self.say = function () { alert(this.name+','+this.age) } } } var c1 = new Child('medong',20,['zhangsan','wangwu']) c1.friend.push('mattt') alert(c1.friend)// ['zhangsan','wangwu','mattt'] var c2 = new Child('jack',30,['mark','jess']) alert(c2.friend)// ['mark','jess']并没有mattt