1、面向对象的工厂方法
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var person1 = createPerson(\"Nicholas\", 29, \"Software Engineer\"); var person2 = createPerson(\"Greg\", 27, \"Doctor\"); person1.sayName(); //\"Nicholas\" person2.sayName(); //\"Greg\"
工厂模型的方法的缺点是会产生大量重复代码!
2、构造函数模式创建对象
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person1 = new Person(\"Nicholas\", 29, \"Software Engineer\"); var person2 = new Person(\"Greg\", 27, \"Doctor\"); person1.sayName(); //\"Nicholas\" person2.sayName(); //\"Greg\" alert(person1 instanceof Object); //true alert(person1 instanceof Person); //true alert(person2 instanceof Object); //true alert(person2 instanceof Person); //true alert(person1.constructor == Person); //true alert(person2.constructor == Person); //true alert(person1.sayName == person2.sayName); //false
使用new关键字创建对象会经历以下四个过程
3、将构造函数当函数用
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person = new Person(\"Nicholas\", 29, \"Software Engineer\"); person.sayName(); //\"Nicholas\" Person(\"Greg\", 27, \"Doctor\"); //adds to window window.sayName(); //\"Greg\" var o = new Object(); Person.call(o, \"Kristen\", 25, \"Nurse\"); o.sayName(); //\"Kristen\"
构造函数当做函数使用就和普通的函数没有任何不同,它属于window对象下面添加的方法而已。由于构造函数创建的对象实际上是创建一个新对象,因此在本质上两者还是不一样的,还是分离的,他们的方法还是不一样的!
4、将共有的方法方法全局解决不一致的问题
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName(){ alert(this.name); } var person1 = new Person(\"Nicholas\", 29, \"Software Engineer\"); var person2 = new Person(\"Greg\", 27, \"Doctor\"); person1.sayName(); //\"Nicholas\" person2.sayName(); //\"Greg\" alert(person1 instanceof Object); //true alert(person1 instanceof Person); //true alert(person2 instanceof Object); //true alert(person2 instanceof Person); //true alert(person1.constructor == Person); //true alert(person2.constructor == Person); //true alert(person1.sayName == person2.sayName); //true
虽然上面的方法解决了一致的问题,但是定义的全局的方法本身属于window,那么局部和全局就没有分开!所以这个方法使用的并不多见!也不建议使用。
5、原型模式
我们创建的任何的一个函数都有一个原型对象,这个属性是一个指针,它指向一个对象,而这个对象的作用是可以有特定的类型的所有的实例共享的方法!
function Person(){ } Person.prototype.name = \"Nicholas\"; Person.prototype.age = 29; Person.prototype.job = \"Software Engineer\"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); person1.sayName(); //\"Nicholas\" var person2 = new Person(); person2.sayName(); //\"Nicholas\" alert(person1.sayName == person2.sayName); //true alert(Person.prototype.isPrototypeOf(person1)); //true alert(Person.prototype.isPrototypeOf(person2)); //true //only works if Object.getPrototypeOf() is available if (Object.getPrototypeOf){ alert(Object.getPrototypeOf(person1) == Person.prototype); //true alert(Object.getPrototypeOf(person1).name); //\"Nicholas\" }
理解原型
无论什么时候只要是创建了一个函数,就会创建一个原型属性,这个属性指向函数的原型对象。在默认的情况下,原型对象都会包含一个constructor(构造函数属性),这个属性包含一个指向prototype属性所在函数的指针!
属性读取的顺序
每当代码读取某个对象的属性时候,都会执行一次搜索,目标是具有给定名字的属性,搜索从对象的实例本身开始查找,如有则返回,没有则继续搜索该对象的原型链,直至搜索到原型链的最外层!
function Person(){ } Person.prototype.name = \"Nicholas\"; Person.prototype.age = 29; Person.prototype.job = \"Software Engineer\"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); person1.name = \"Greg\"; alert(person1.name); //\"Greg\" 来自实例 alert(person2.name); //\"Nicholas\" 来自原型
如果删除了这个元素的实例属性
function Person(){ } Person.prototype.name = \"Nicholas\"; Person.prototype.age = 29; Person.prototype.job = \"Software Engineer\"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); person1.name = \"Greg\"; alert(person1.name); //\"Greg\" ?from instance alert(person2.name); //\"Nicholas\" ?from prototype delete person1.name; alert(person1.name); //\"Nicholas\" - from the prototype
6、hasOwnProperty方法
这个方法可以检测一个属性是否存在于实例中,还是存在于原型中!hasOwnProperty是从Object继承来的,只要给定属性存在于对象实例中,才会返回true.
function Person(){ } Person.prototype.name = \"Nicholas\"; Person.prototype.age = 29; Person.prototype.job = \"Software Engineer\"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); alert(person1.hasOwnProperty(\"name\")); //false alert(\"name\" in person1); //true person1.name = \"Greg\"; alert(person1.name); //\"Greg\" ?from instance alert(person1.hasOwnProperty(\"name\")); //true alert(\"name\" in person1); //true alert(person2.name); //\"Nicholas\" ?from prototype alert(person2.hasOwnProperty(\"name\")); //false alert(\"name\" in person2); //true delete person1.name; alert(person1.name); //\"Nicholas\" - from the prototype alert(person1.hasOwnProperty(\"name\")); //false alert(\"name\" in person1); //true
7、Object.keys() 可枚举属性方法
这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组
function Person(){ } Person.prototype.name = \"Nicholas\"; Person.prototype.age = 29; Person.prototype.job = \"Software Engineer\"; Person.prototype.sayName = function(){ alert(this.name); }; var keys = Object.keys(Person.prototype); alert(keys); //\"name,age,job,sayName\" 如果想得到所有实例的属性,无论它是否可以枚举都可以使用这个方法来获取 function Person(){ } Person.prototype.name = \"Nicholas\"; Person.prototype.age = 29; Person.prototype.job = \"Software Engineer\"; Person.prototype.sayName = function(){ alert(this.name); }; var keys = Object.getOwnPropertyNames(Person.prototype); alert(keys); //\"constructor,name,age,job,sayName\"
此方法高版本浏览器才支持
8、简单的原型写法
function Person(){ } Person.prototype = { name : \"Nicholas\", age : 29, job: \"Software Engineer\", sayName : function () { alert(this.name); } }; var friend = new Person(); alert(friend instanceof Object); //true alert(friend instanceof Person); //true alert(friend.constructor == Person); //false alert(friend.constructor == Object); //true
重写了原型就等于将默认的原型方法覆盖,那么同样的构造方法也会被重写,重写的构造方法指向了Object对象!而不是原来的对象Person
如果还是想指向之前的构造方法,可以显示的指定
function Person(){ } Person.prototype = { constructor : Person, name : \"Nicholas\", age : 29, job: \"Software Engineer\", sayName : function () { alert(this.name); } }; var friend = new Person(); alert(friend instanceof Object); //true alert(friend instanceof Person); //true alert(friend.constructor == Person); //true alert(friend.constructor == Object); //false
9、原型方法的动态添加
function Person(){ } Person.prototype = { constructor: Person, name : \"Nicholas\", age : 29, job : \"Software Engineer\", sayName : function () { alert(this.name); } }; var friend = new Person(); Person.prototype.sayHi = function(){ alert(\"hi\"); }; friend.sayHi(); //\"hi\" ?works!
10、原生对象的原型方法
alert(typeof Array.prototype.sort); //\"function\" alert(typeof String.prototype.substring); //\"function\" String.prototype.startsWith = function (text) {//修改原生对象的原型方法 return this.indexOf(text) == 0; }; var msg = \"Hello world!\"; alert(msg.startsWith(\"Hello\")); //true
11、组合使用构造函数和原型模式创建对象
//构造函数模式 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = [\"Shelby\", \"Court\"]; } //原型模式 Person.prototype = { constructor: Person, sayName : function () { alert(this.name); } }; var person1 = new Person(\"Nicholas\", 29, \"Software Engineer\"); var person2 = new Person(\"Greg\", 27, \"Doctor\"); person1.friends.push(\"Van\"); alert(person1.friends); //\"Shelby,Court,Van\" alert(person2.friends); //\"Shelby,Court\" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true
12、动态原型模式
function Person(name, age, job){ //properties this.name = name; this.age = age; this.job = job; //methods if (typeof this.sayName != \"function\"){ Person.prototype.sayName = function(){ alert(this.name); }; } } var friend = new Person(\"Nicholas\", 29, \"Software Engineer\"); friend.sayName();
13、寄生构造函数模式
function Person(name, age, job){ var o = new Object();//依赖全局对象初始化一个对象,然后再返回这个对象 o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var friend = new Person(\"Nicholas\", 29, \"Software Engineer\"); friend.sayName(); //\"Nicholas\" function SpecialArray(){ //create the array var values = new Array(); //add the values values.push.apply(values, arguments); //assign the method values.toPipedString = function(){ return this.join(\"|\"); }; //return it return values; } var colors = new SpecialArray(\"red\", \"blue\", \"green\"); alert(colors.toPipedString()); //\"red|blue|green\" alert(colors instanceof SpecialArray);
上诉方法有一点说明下,由于它是依赖外层对象来创建一个新对象,因此不能依赖 instanceof方法来确定属性和方法的来源!它实际上和构造函数的没有关系!
14、稳妥构造函数模式
function Person(name, age, job){ var o = new Object(); o.sayName = function(){ alert(name); }; return o; } var friend = Person(\"Nicholas\", 29, \"Software Engineer\"); friend.sayName(); //\"Nicholas\"
此方法不依赖任何new this 关键符!如果要访问对象的方法和属性,只能通过对象已经定义好的方法来获取!
15、继承
javascript实现继承是通过原型链来实现的
function SuperType(){ this.property = true;//定义一个属性 } SuperType.prototype.getSuperValue = function(){//定义的原型方法 return this.property; }; function SubType(){ this.subproperty = false; } //inherit from SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function (){ return this.subproperty; }; var instance = new SubType(); alert(instance.getSuperValue()); //true alert(instance instanceof Object); //true alert(instance instanceof SuperType); //true alert(instance instanceof SubType); //true alert(Object.prototype.isPrototypeOf(instance)); //true alert(SuperType.prototype.isPrototypeOf(instance)); //true alert(SubType.prototype.isPrototypeOf(instance)); //true SubType继承SuperType的方法和属性,因此当instance可以直接调用SuperType的方法! function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //inherit from SuperType SubType.prototype = new SuperType(); //new method SubType.prototype.getSubValue = function (){ return this.subproperty; }; //override existing method SubType.prototype.getSuperValue = function (){ return false; }; var instance = new SubType(); alert(instance.getSuperValue()); //false
上面的例子说明,重写的原型会覆盖之前继承的原型,最后返回的往往不是预期的效果
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //inherit from SuperType SubType.prototype = new SuperType(); //使用字面量添加的方法导致上面的方法失效了 SubType.prototype = { getSubValue : function (){ return this.subproperty; }, someOtherMethod : function (){ return false; } }; var instance = new SubType(); console.log(instance); alert(instance.getSuperValue()); //error!
下面的例子也说明重写原型带来的风险
function SuperType(){ this.colors = [\"red\", \"blue\", \"green\"]; } function SubType(){ } //inherit from SuperType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push(\"black\"); alert(instance1.colors); //\"red,blue,green,black\" var instance2 = new SubType(); alert(instance2.colors); //\"red,blue,green,black\"
原型共享导致两个不同的对象调用的同一个数据
16、借用构造函数来实现继承
function SuperType(){ this.colors = [\"red\", \"blue\", \"green\"]; } function SubType(){ //inherit from SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push(\"black\"); alert(instance1.colors); //\"red,blue,green,black\" var instance2 = new SubType(); alert(instance2.colors); //\"red,blue,green\"
传递参数
function SuperType(name){ this.name = name; } function SubType(){ //inherit from SuperType passing in an argument SuperType.call(this, \"Nicholas\"); //instance property this.age = 29; } var instance = new SubType(); alert(instance.name); //\"Nicholas\"; alert(instance.age); //29
17、组合继承方式
function SuperType(name){ this.name = name; this.colors = [\"red\", \"blue\", \"green\"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ SuperType.call(this, name); this.age = age; }
18、原型继承
function object(o){ function F(){} F.prototype = o; return new F(); } var person = { name: \"Nicholas\", friends: [\"Shelby\", \"Court\", \"Van\"] }; var anotherPerson = object(person); anotherPerson.name = \"Greg\"; anotherPerson.friends.push(\"Rob\");
19、寄生组合式继承
function object(o){ function F(){} F.prototype = o; return new F(); } function inheritPrototype(subType, superType){ var prototype = object(superType.prototype); //create object prototype.constructor = subType; //augment object subType.prototype = prototype; //assign object } function SuperType(name){ this.name = name; this.colors = [\"red\", \"blue\", \"green\"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ SuperType.call(this, name); this.age = age; } inheritPrototype(SubType, SuperType); SubType.prototype.sayAge = function(){ alert(this.age); }; var instance1 = new SubType(\"Nicholas\", 29); instance1.colors.push(\"black\"); alert(instance1.colors); //\"red,blue,green,black\" instance1.sayName(); //\"Nicholas\"; instance1.sayAge(); //29 var instance2 = new SubType(\"Greg\", 27); alert(instance2.colors); //\"red,blue,green\" instance2.sayName(); //\"Greg\"; instance2.sayAge(); //27
以上就是今天的javascript学习小结,之后每天还会继续更新,希望大家继续关注。
本文地址:https://www.stayed.cn/item/23168
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我