摘要:一创建对象工厂模式构造函数模式和都是的不同实例。寄生构造函数模式不使用和创建要返回的对象可以在这里添加私有变量和函数添加方法注意,在以这种模式创建的对象中,除了使用方法之外,没有其他办法访问的值
一:创建对象
1 工厂模式
function createPerson(name, age, jod){ var obj = new Object(); obj.name = name; obj.age = age; obj.job = job; obj.sayName = function(){ console.log(this.name); }; return obj; } var person1 = createPerson("NEVAR", 23, "Front-end Engineer"); var person2 = createPerson("Amy", 27, "Doctor");
2 构造函数模式
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ console.log(this.name); } } var person1 = new Person("NEVAR", 23, "Front-end Engineer"); var person2 = new Person("Amy", 27, "Doctor"); //person1和person2都是Person的不同实例。 alert(person1.constructor == Person); //true alert(person2.constructor == Person); //true //即是Object的实例也是Person的实例 alert(person1 instanceof Object); //true alert(person1 instanceof Person); //true //构造函数产生的是两个不同实例,同名函数是不相等的 alert(person1.sayName == person2.sayName); //false
3 原型模式
function Person(){ } Person.prototype.name = "NEVAR"; Person.prototype.age = 23; Person.prototype.job = "Front-end Engineer"; Person.prototype.sayName = function(){ console.log(this.name); }; var person1 = new Person(); person1.sayName(); //NEVAR var person2 = new Person(); person2.sayName; //NEVAR console.log(person1.sayName == person2.sayName);// true var person3 = new Person(); person3.name = "PP"; console.log(person3.name); //PP 来自实例 delete person3.name; console.log(person3.name); //NEVAR 来自原型 alert(person1.hasOwnProperty("name")); //false 来自原型 alert(person3.hasOwnProperty("name")); //true 来自实例 alert("name" in person1); //true in操作符的使用 function hasPrototypeProperty (obj, name){ return !obj.hasOwnProperty(name) && (name in obj) } //判断属性来自实例 真 然后取反 //并且name属性存在于obj原型链上 说明这个 属性是属于prototype的 alert(hasPrototypeProperty(person1,"name")) // true alert(hasPrototypeProperty(person3,"name")) // false alert(Object.keys(Person.prototype)) //"name,age,job,sayName" //Person的可枚举属性
不过以上方法太过于麻烦 每次都要写重复的prototype
function Person(){ } Person.prototype = { name : "NEVAR", age : "23", job : "Front-end Engineer", sayName : function(){ console.log(this.name); } };
constructor 属性不再指向Person 了 指向Object
var friend = new Person(); alert(friend instanceof Object); //true alert(friend instanceof Person); //true alert(friend.constructor == Person); //false alert(friend.constructor == Object); //true
于是可以这样
Person.prototype = { constructor : Person, name : "NEVAR", age : "23", job : "Front-end Engineer", sayName : function(){ console.log(this.name); } };
原型的动态性
var friend = new Person(); Person.prototype.sayHi = function(){ alert("Hi"); } friend.sayHi();//Hi //这时没有问题,如果我们重写原型对象 那么情况就不一样了 function Person(){ } var friend = new Person(); Person.prototype = { constructor: Person, name : "NEVAR", age : 23, job : "Front-end Engineer", sayName : function () { alert(this.name); } }; friend.sayName(); //error
重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系;它们引用的仍然是最初的原型。
原型模式也不是没有缺点。首先,它省略了为构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值
对于那些包含基本值的属性倒也说得过去,毕竟(如前面的例子所示),通过在实例上添加一个同名属性,可以隐藏原型中的对应属性。然而,对于包含引用类型值的属性来说,问题就比较突出了
function Person(){ } Person.prototype = { constructor: Person, name : "Nicholas", age : 29, job : "Software Engineer", friends : ["Shelby", "Court"], sayName : function () { alert(this.name); } }; var person1 = new Person(); var person2 = new Person(); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Court,Van" alert(person2.friends); //"Shelby,Court,Van" alert(person1.friends === person2.friends); //true
4组合使用构造函数模式和原型模式
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Shelby","Court"]; } Person.prototype = { constructor : Person, sayName : function(){ console.log(this.name); } } var person1 = new Person("NEVAR", 23, "Front-end Engineer"); var person2 = new Person("Amy", 27, "Doctor"); person1.friends.push("Van"); console.log(person1.friends) //"Shelby,Court,Van" console.log(person2.friends) //"Shelby,Court" console.log(person1.friends === person2.friends); // false console.log(person1.sayName === person2.sayName); //true
5动态原型模式
它把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点。换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; if(typeof this.sayName != function){ Person.prototype.sayName = function(){ console.log(this.name); } } } var person1 = new Person("NEVAR", 23, "Front-end Engineer"); friend.sayName();
6寄生构造函数模式
//不使用this和new function Person(name, age, job){ //创建要返回的对象 var o = new Object(); //可以在这里添加私有变量和函数 //添加方法 o.sayName = function(){ console.log(name); } return o; }
注意,在以这种模式创建的对象中,除了使用sayName()方法之外,没有其他办法访问name 的值
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78983.html
摘要:继承原型链如果构造函数或对象的原型指向构造函数或对象,的原型再指向构造函数或对象,以此类推,最终的构造函数或对象的原型指向的原型。 继承 原型链 如果构造函数或对象A的原型指向构造函数或对象B,B的原型再指向构造函数或对象C,以此类推,最终的构造函数或对象的原型指向Object的原型。由此形成了一条链状结构,被称之为原型链。按照上述的描述,在B中定义的属性或方法,可以在A中使用并不需要...
摘要:使用最多的继承模式是组合继承,这种模式使用原型链继承共享的属性和方法,而借用构造函数继承实例属性。原型式继承,可以在不必预先定义构造函数的情况下实现继承,其本质是执行给定对象的浅复制。 1、原型链实现继承 function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = func...
摘要:即另外,注意到构造函数里的属性,都没有经过进行初始化,而是直接使用进行绑定。并且在模式下,构造函数没有使用进行调用,也会导致报错。调用构造函数千万不要忘记写。 1. 基础 JavaScript不区分类和实例的概念,而是通过原型来实现面向对象编程。Java是从高级的抽象上设计的类和实例,而JavaScript的设计理念,听起来就好比Heros里的Peter,可以复制别人的能力。JavaS...
摘要:实际上,可以将其理解为某种形式的继承。如果上下文是,则使用全局对象代替。例如的第个参数是上下文,后续是实际传入的参数序列中允许更换上下文是为了共享状态,尤其是在事件回调中。 公开记录学习JS MVC,不知道能坚持多久= =。以《基于MVC的JavaScript web富应用开发》为主要学习资料。接上一篇类的学习,发现实在是看晕了,有些例子是能看懂在干嘛,但是不知道为什么这样做,有的甚至...
摘要:实现原型链的方式如下让原型对象称为另一个构造函数的实例这个实例继承了的属性上述代码继承是通过来实现,创建的实例,并将该实例赋给。无疑,集两者之大成,这才是最常用的继承模式。 原型链 JavaScript的继承主要依靠原型链来实现的。我们知道,构造函数,原型,和实例之间的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个原型对象的指针。 实现原型链...
摘要:第二个问题是在创建子类型的实例时,不能向超类型的构造函数中传递参数。实际上,应该说是没有办法在不影响所有对象实例的情况下,给炒类型的构造函数传递参数。借用构造函数伪造对象或经典继承即在子类型构造函数的内部调用超类型构造函数。 继承 许多 OO 语言支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。如前所述,由于函数没有签名,在 ECMAScri...
阅读 4619·2021-10-25 09:48
阅读 3210·2021-09-07 09:59
阅读 2166·2021-09-06 15:01
阅读 2692·2021-09-02 15:21
阅读 2731·2019-08-30 14:14
阅读 2182·2019-08-29 13:59
阅读 2513·2019-08-29 11:02
阅读 2531·2019-08-26 13:33