JavaScript对象的创建之基于原型方式
原型内存模型介绍
原型是javascript中非常特殊的一个对象,当一个函数创建之后,会随之就产生一个原型对象。
当通过这个函数的构造函数创建一个具体的对象之后,在这个具体的对象中就会有一个属性指向原型。
第一种状态
function Person(){
}
function Person(){},Person函数中有一个prototype的属性指向了Person Prototype的原型对象,在原型对象中有一个constructor的属性指向了Person函数,所以可以通过new Person()创建对象。内存图如下所示:
第二种状态
Person.prototype.name=”zhangsan”;
Person.prototype.age = 27;
Person.prototype.say = function(){
alert(this.name + “,” + this.age);
}
通过Person.prototype.name为原型设置值之后,这些属性和方法都是设置在Person原型中。内存图如下所示:
第三种状态
var p1 = new Person();
p1.say(); //检测某个对象是否是某个函数的原型
//以下方法可以检测出p1是否有_prop_指向Person的原型
Person.prototype.isPrototypeOf(p1)
当使用Person创建了对象之后,会在对象中有一个_prop_属性(这个属性是不能被访问的)指向了原型,当使用对象调用原型的时候,首先会在对象的内部找是否有这个属性,如果没有会通过_prop_去原型中找属性,所以当调用p1.say(),在自己的空间中不存在这个方法,就会去原型中寻找,找到之后完成say的调用。内存图如下所示:
第四种状态
var p2 = new Person();
p2.name = “luogankun”; //是在自己的空间中定义了一个属性,不会替换原型中的属性
p2.say();
当创建了一个新的p2之后,依然会有一个_prop_属性指向Person的原型,此时如果通过p2.name=”luogankun”设置了属性之后,会在对象自己的内存空间中存储name的值,当调用say方法的时候在寻找name时,在自己的空间中找到之后,就不会去原型中查找了。(特别注意:原型中的值不会被替换,仅仅只是在查找时被覆盖)。内存图如下所示:
其他方法介绍
检测某个对象是否是某个函数的原型
alert(Person.prototype.isPrototypeOf(p2)); //true
检测某个对象的constructor
alert(p1.constructor==Person); //true
检测某个属性是否是自己的属性
alert(p1.hasOwnProperty("name")); //false , p1自己的空间中没有值
alert(p2.hasOwnProperty("name")); //true,p2在自己的空间中设置了name属性 p2.say(); // luogankun 27
delete p2.name;
p2.say(); //zhangsan 27
alert(p2.hasOwnProperty("name")); //由于已经删除了,所以是false
检测某个对象在原型或者自己中是否包含有某个属性,通过in检测
alert("name" in p1); //true
alert("name" in p2); //true
alert("address" in p1); //在原型和自己的空间中都没有,false alert(hasPrototypeProperty(p1,"name"));//true
alert(hasPrototypeProperty(p2,"name"));//false 可以通过如下方法检测某个属性是否在原型中存在(在原型中但是不在自己空间中)
// prop in obj表示原型和自己中有,!obj.hasOwnProperty(prop)表示自己中没有
function hasPrototypeProperty(obj,prop) {
return ((!obj.hasOwnProperty(prop))&&(prop in obj))
}
原型重写
以上代码中当属性和方法特别多时,编写起来不是很方便,可以通过json的格式。json格式将会重写原型
function Person(){}
//重写原型
Person.prototype = {
constructor:Person,//手动指定constructor
name:"Leon",
age:23,
say:function() {
alert(this.name+","+this.age);
}
}
var p1 = new Person();
p1.say();
alert(p1.constructor==Person); //true, 如果不显示的添加构造,此处打印出false
原型重写内存模型1
function Person(){}
Person.prototype = {
constructor:Person,//手动指定constructor
name:"Leon",
age:23,
say:function() {
alert(this.name+","+this.age);
}
}
var p1 = new Person();
Person.prototype.sayHi = function() {
alert(this.name+":hi");
}
p1.sayHi(); // Leon:hi
内存图如下所示:
原型重写内存模型2
如果把重写放置在new Person()之后,注意内存模型:
function Person(){}
var p1 = new Person();
Person.prototype.sayHi = function() {
alert(this.name+":hi");
}
Person.prototype = {
constructor:Person,//手动指定constructor
name:"Leon",
age:23,
say:function() {
alert(this.name+","+this.age);
}
}
p1.sayHi(); //undefined :hi 没有报错但是没有name
内存模型如下所示:
原型重写内存模型3
function Person(){}
var p1 = new Person();
Person.prototype.sayHi = function() {
alert(this.name+":hi");
}
Person.prototype = {
constructor:Person,//手动指定constructor
name:"Leon",
age:23,
say:function() {
alert(this.name+","+this.age);
}
}
p1.sayHi(); //undefined :hi 没有报错但是没有name
var p2 = new Person();
p2.sayHi(); //报错
内存模型如下所示:
原型重写存在的问题
基于原型的创建虽然可以有效的完成封装,但是依然有一些问题:
1、法通过构造函数来设置属性值;
2、当属性中有引用类型变量时,可能存在变量值重复
function Student(){
}
Student.prototype.username = new Array();
Student.prototype.password = "123";
Student.prototype.getInfo = function(){
alert(this.username + "-->" + this.password);
}
var s1 = new Student();
var s2 = new Student();
s1.username.push("ww");
s1.username.push("ss");
s1.password = "111";
s1.getInfo(); //ww ss 111
s2.getInfo(); //ww ss 123
内存模型如下所示:
JavaScript对象的创建之基于原型方式的更多相关文章
- JavaScript对象的创建之动态原型方式
为了让定义的方式更加符合java的需求,就把定义方法的原型代码放置在Person这个构造函数中. function Person(name,age,friends){ //属性在构造函数中定义 thi ...
- JavaScript对象的创建之基于构造方法+原型方式
为了解决原型所带来的问题,此处需要通过组合构造方法和原型来实现对象的创建,将属性在构造方法中定义,将方法在原型中定义.这种有效集合了两者的优点,是目前最为常用的一种方式. function Perso ...
- JavaScript对象属性访问的两种方式
JavaScript对象属性访问的两种方式 object.attribute object["attribute"] 例如: var employees = [ { "f ...
- javascript面向对象 用new创建一个基于原型的javascript对象
//创建一个类 其实就是个对象 var Student={ name:"robot", height:1.6, run:function(){ console.log(this.n ...
- JavaScript对象的创建
原文 简书原文:https://www.jianshu.com/p/6cb1e7b7e379 大纲 前言 1.简单方式创建对象的方法 2.工厂模式创建对象 3.构造函数模式创建对象 4.原型模式创建对 ...
- JavaScript 对象的创建
Object类型是JavaScript中使用最多的一种类型.创建Object实例的方式有多种,接下来一一列举. 1. Object构造函数 person1的friends属性修改影响了person2的 ...
- JavaScript对象的创建总结
方式 缺点 优点 基于已有对象扩充属性和方法 不可重用,没有约束 无 工厂方法 检测不出是什么的实例 简单封装,可以传参 构造方法 每创建一个对象就有开辟存放方法的空间 能通过instanceof检测 ...
- javascript对象的创建--相对java 怎样去创建了"类"i以及实例化对象
由于javascript没有java那么多基本类型,同时也没有提供class这个东西,那么我们想实现javascript的对象创建应该怎么办呢,我简单地从w3c提供的课件中提取了一下几种方法: 一.工 ...
- JavaScript对象的创建之构造函数
通过构造函数的方式创建和基于工厂的创建类似,最大的区别就是函数的名称就是类的名称,按照java的约定,第一个字母大写. 使用构造函数创建对象时,在函数内部是通过this关键字来完成属性的定义. fun ...
随机推荐
- javascript取得机器名,用户名,读写注册表,启动应用程序
javascript取得机器名,用户名,读写注册表,启动应用程序//javascript有个特殊的对象ActiveXObject,通过它可以访问windows的本地文件系统和应用程序,比如:有的时候我 ...
- HTML 列表
HTML 支持有序.无序和定义列表 实例 无序列表 本例演示无序列表. 有序列表 本例演示有序列表. (可以在本页底端找到更多实例.) 无序列表 无序列表是一个项目的列表,此列项目使用粗体圆点(典型的 ...
- 【jmeter】JMeter测试MongoDB
JMeter测试MongoDB性能有两种方式,一种是利用JMeter直接进行测试MongoDB,还有一种是写Java代码方式测试MongoDB性能. 第一种方法 1.编写Java代码,内容如下: pa ...
- LintCode "Digit Counts" !!
Lesson learnt: one effective solution for bit\digit counting problems: counting by digit\bit http:// ...
- bzoj4165: 矩阵
Description 定义和谐矩阵为长不小于 Mina 且宽不小于 Minb 的矩阵,矩阵的权值为整个矩阵内所有数的和.给定一个长为 N ,宽为 M 的矩阵 A,求它的所有和谐子矩阵中权值第 K 小 ...
- 242. Valid Anagram
Given two strings s and t, write a function to determine if t is an anagram of s. For example,s = &q ...
- 【转】SQL SERVER标量表达式的隐式转换
在SQL Server中的数据类型中,存在着优先级的问题.标量表达示的返回结果类型也会根据操作数的类型而定,如1 +'1'=2.而不是'11',因些Int型的优先级比VARCHAR型的优先级要高.所以 ...
- ios之"performSelector may cause a leak because its selector is unknown"警告原因及其解决办法
问题描述 项目中使用到了从字符串创建选择器,编译时发现警告:"performSelector may cause a leak because its selector is unknown ...
- Spark读写Hbase中的数据
def main(args: Array[String]) { val sparkConf = new SparkConf().setMaster("local").setAppN ...
- SOA_环境安装系列4_Oracle SOA安装和环境搭建(案例)
2015-01-02 Created By BaoXinjian