js构造函数实例讲解
作者:佳明妈 来源:http://caibaojian.com/ 2016-06-29 人气:构造函数的方法是定义在函数内容,作为一个私有方法,不对外开放,而prototype则可以通过对象定义,在外面访问。 为了阅读方便,我们约定一下:把方法写在构造函数内的情况我们简称
js构造函数的方法是定义在函数内容,作为一个私有方法,不对外开放,而prototype则可以通过对象定义,在外面访问。
为了阅读方便,我们约定一下:把方法写在构造函数内的情况我们简称为函数内方法,把方法写在prototype属性上的情况我们简称为prototype上的方法
为了阅读方便,我们约定一下:把方法写在构造函数内的情况我们简称为函数内方法,把方法写在prototype属性上的情况我们简称为prototype上的方法
本文重点:
函数内的方法: 使用函数内的方法我们可以访问到函数内部的私有变量,如果我们通过构造函数new出来的对象需要我们操作构造函数内部的私有变量的话, 我们这个时候就要考虑使用函数内的方法.
prototype上的方法: 当我们需要通过一个函数创建大量的对象,并且这些对象还都有许多的方法的时候;这时我们就要考虑在函数的prototype上添加这些方法. 这种情况下我们代码的内存占用就比较小.
在实际的应用中,这两种方法往往是结合使用的;所以我们要首先了解我们需要的是什么,然后再去选择如何使用.
代码看重点:
代码看重点:
// 构造函数A
function A(name) {
this.name = name || 'a';
this.sayHello = function() {
console.log('Hello, my name is: ' + this.name);
}
}
// 构造函数B
function B(name) {
this.name = name || 'b';
}
B.prototype.sayHello = function() {
console.log('Hello, my name is: ' + this.name);
};
var a1 = new A('a1');
var a2 = new A('a2');
a1.sayHello();
a2.sayHello();
var b1 = new B('b1');
var b2 = new B('b2');
b1.sayHello();
b2.sayHello();
我们首先写了两个构造函数,第一个是A,这个构造函数里面包含了一个方法sayHello;第二个是构造函数B, 我们把那个方法sayHello写在了构造函数B的prototype属性上面.
需要指出的是,通过这两个构造函数new出来的对象具有一样的属性和方法,但是它们的区别我们可以通过下面的一个图来说明:
我们通过使用构造函数A创建了两个对象,分别是a1,a2;通过构造函数B创建了两个对象b1,b2;我们可以发现b1,b2这两个对象的那个sayHello方法 都是指向了它们的构造函数的prototype属性的sayHello方法.而a1,a2都是在自己内部定义了这个方法. 定义在构造函数内部的方法,会在它的每一个实例上都克隆这个方法;定义在构造函数的prototype属性上的方法会让它的所有示例都共享这个方法,但是不会在每个实例的内部重新定义这个方法. 如果我们的应用需要创建很多新的对象,并且这些对象还有许多的方法,为了节省内存,我们建议把这些方法都定义在构造函数的prototype属性上
当然,在某些情况下,我们需要将某些方法定义在构造函数中,这种情况一般是因为我们需要访问构造函数内部的私有变量.
下面我们举一个两者结合的例子,代码如下:
function Person(name, family) {
this.name = name;
this.family = family;
var records = [{type: "in", amount: 0}];
this.addTransaction = function(trans) {
if(trans.hasOwnProperty("type") && trans.hasOwnProperty("amount")) {
records.push(trans);
}
}
this.balance = function() {
var total = 0;
records.forEach(function(record) {
if(record.type === "in") {
total += record.amount;
}
else {
total -= record.amount;
}
});
return total;
};
};
Person.prototype.getFull = function() {
return this.name + " " + this.family;
};
Person.prototype.getProfile = function() {
return this.getFull() + ", total balance: " + this.balance();
};
在上面的代码中,我们定义了一个Person构造函数;这个函数有一个内部的私有变量records,这个变量我们是不希望通过函数内部以外的方法 去操作这个变量,所以我们把操作这个变量的方法都写在了函数的内部.而把一些可以公开的方法写在了Person的prototype属性上,比如方法getFull和getProfile.
把方法写在构造函数的内部,增加了通过构造函数初始化一个对象的成本,把方法写在prototype属性上就有效的减少了这种成本. 你也许会觉得,调用对象上的方法要比调用它的原型链上的方法快得多,其实并不是这样的,如果你的那个对象上面不是有很多的原型的话,它们的速度其实是差不多的
另外,需要注意的一些地方:
首先如果是在函数的prototype属性上定义方法的话,要牢记一点,如果你改变某个方法,那么由这个构造函数产生的所有对象的那个方法都会被改变.
还有一点就是变量提升的问题,我们可以稍微的看一下下面的代码:
func1(); // 这里会报错,因为在函数执行的时候,func1还没有被赋值. error: func1 is not a function
var func1 = function() {
console.log('func1');
};
func2(); // 这个会被正确执行,因为函数的声明会被提升.
function func2() {
console.log('func2');
}
关于对象序列化的问题.定义在函数的prototype上的属性不会被序列化,可以看下面的代码:
function A(name) {
this.name = name;
}
A.prototype.sayWhat = 'say what...';
var a = new A('dreamapple');
console.log(JSON.stringify(a));
我们可以看到输出结果是{"name":"dreamapple"}
原文:http://caibaojian.com/js-constructor-vs-prototype.html
下面的博客作者豪情直接用js代码的形式来注释js构造函数,看起来很不错,一目了然。
原文:http://caibaojian.com/js-constructor-vs-prototype.html
下面的博客作者豪情直接用js代码的形式来注释js构造函数,看起来很不错,一目了然。
//js构造函数代码注解 //使自己的对象多次复制,同时实例根据设置的访问等级可以访问其内部的属性和方法 //当对象被实例化后,构造函数会立即执行它所包含的任何代码 function myObject(msg){ //特权属性(公有属性) this.myMsg = msg; //只在被实例化后的实例中可调用 this.address = '上海'; //私有属性 var name = '豪情'; var age = 29; var that = this; //私有方法 function sayName(){ alert(that.name); } //特权方法(公有方法) //能被外部公开访问 //这个方法每次实例化都要重新构造而prototype是原型共享,所有实例化后,都共同引用同一个 this.sayAge = function(){ alert(name); //在公有方法中可以访问私有成员 } //私有和特权成员在函数的内部,在构造函数创建的每个实例中都会包含同样的私有和特权成员的副本, //因而实例越多占用的内存越多 } //公有方法 //适用于通过new关键字实例化的该对象的每个实例 //向prototype中添加成员将会把新方法添加到构造函数的底层中去 myObject.prototype.sayHello = function(){ alert('hello everyone!'); } //静态属性 //适用于对象的特殊实例,就是作为Function对象实例的构造函数本身 myObject.name = 'china'; //静态方法 myObject.alertname = function(){ alert(this.name); } //实例化 var m1 = new myObject('111'); //---- 测试属性 ----// //console.log(myObject.name); //china //console.log(m1.name); //undefined, 静态属性不适用于一般实例 //console.log(m1.constructor.name); //china, 想访问类的静态属性,先访问该实例的构造函数,然后在访问该类静态属性 //console.log(myObject.address); //undefined, myObject中的this指的不是函数本身,而是调用address的对象,而且只能是对象 //console.log(m1.address); //上海 此时this指的是实例化后的m1 //---- 测试方法 ----// //myObject.alertname(); //china,直接调用函数的类方法 //m1.alertname(); //FF: m1.alertname is not a function, alertname 是myObject类的方法,和实例对象没有直接关系 //m1.constructor.alertname(); //china, 调用该对象构造函数(类函数)的方法(函数) //m1.sayHello(); //hello everyone, myObject类的prototype原型下的方法将会被实例继承 //myObject.sayHello(); //myObject.sayHello is not a function,sayHello是原型方法,不是类的方法 //---- 测试prototype ----// //console.log(m1.prototype); //undefined, 实例对象没有prototype //console.log(myObject.prototype); //Object //alert(myObject.prototype.constructor); //console.log返回myObject(msg),此时alert()更清楚,相当于myObject //console.log(myObject.prototype.constructor.name); //china, 相当于myObject.name; 来源:http://www.cnblogs.com/jikey/archive/2011/05/13/2045005.html
↓ 查看全文
js构造函数实例讲解由懒人建站收集整理,您可以自由传播,请主动带上本文链接
懒人建站就是免费分享,觉得有用就多来支持一下,没有能帮到您,懒人也只能表示遗憾,希望有一天能帮到您。
- 上一篇:javascript的起源
- 下一篇:js继承的实现
js构造函数实例讲解-最新评论