js建立对象有许多要领,以下是罕见要领整顿。
ES5建立对象
工场形式
function person (name, age, sex) {
var O = new Object();
O.name = name;
O.age = age;
O.sex = sex;
O.sayName =function(){
console.log(this.name);
}
return O;
}
var per = person("per",10,"male"); //不需要用new,由于有return,就是个一般函数,很好明白
console.log(per instanceof person); //false
组织函数形式
function Person (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.sayName =function(){
console.log(this.name);
}
}
var per =new Person("per",10,"male");
console.log(per instanceof Person); //true
剖析建立历程,
var per =new Person("per",10,"male");
在这行代码实行时,四个步骤:
①涌现了一个空的对象
②this指向这个对象
③实行组织函数的代码
④把这个对象取个名字是per,per的指针就指向这个对象,因而能够经由过程per操纵这个对象
工场形式定义出的对象,instanceof辨认不出是”person类”。
组织函数形式,每次new一个对象,内里的函数都邑建立一次,就这个sayName函数,明显共有同一个就能够了。
处理这个题目,涌现了原型形式:
原型形式
function Person () {
Person.prototype.name = "p1";
Person.prototype.age = 10;
Person.prototype.sex = "female";
Person.prototype.sayName =function(){
console.log(this.name);
}
}
那末,这些代码干了什么呢?
①当你建立Person()函数后,就会有一个prototype属性随之而来
我们能够看看,这个prototype是什么,实行以下代码:
console.log(Person.prototype);
_proto_保留继续自Object的要领。内里只要一个constructor属性指向Person()函数本身。
②固然我们是要用这个函数的,实行以下代码:
var per1 =new Person();
var per2 =new Person();
console.log(Person.prototype);
在建立现实对象时刻,就会运转组织函数中的代码,而且per1、per2两个对象,就会实行两次组织函数的代码,但并不会多建立一个Person的prototype属性,只是从新赋值内里的name、age、sex和sayName变量。
③per1和per2有各自的prototype属性,指向Person的prototype属性。能够简朴明白为per1、per2各自的”指针”指向同一个”对象”。
这个原型形式啊,就真的彷佛单例形式了,每一个建立的对象都在操纵同一个对象。
最优:动态原型形式
function Person (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
console.log(this.name);
}
Person.prototype.sayAge = function(){
console.log(this.age);
}
}
}
var per = new Person("wlq", 19, "man");
如许的代码,使得每一个对象的name、age、sex都是各自的(不共有),然后函数写在原型上,就又是同享的,很不错。另有个处所,if语句的推断,使得第二次建立对象时刻,不会从新给Person.prototype.sayName和Person.prototype.sayAge重赋值。
原型重写的题目
function Person (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
console.log(this.name);
}
}
}
function WPerson (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
if(typeof this.sayName != "function"){
WPerson.prototype = { //这里进行了原型的重写
constructor: WPerson,
sayName: function(){
console.log(this.name);
}
}
}
}
var per1 = new Person("w", 19, "man");
var per2 = new WPerson("q", 18, "man");
var per3 = new WPerson("q", 18, "man");
per1.sayName(); //输出w
per2.sayName(); //报错,说没有sayName这个要领
per3.sayName(); //输出q
console.log(per2.name); //输出q
缘由
重写原型的发作是在建立对象今后的,per2指向的WPerson的原型上面只要name、age、sex,再建立完per2后,才实行WPerson原型的重写,per3以至今后建立的WPerson范例对象就都邑有sayName函数了。
革新要领
要领一(经由过程先实行一次WPerson的原型重写):
function WPerson (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
WPerson.prototype = { //写在建立对象之前
constructor:WPerson,
sayName: function(){
console.log(this.name);
}
}
var per = new WPerson("q", 18, "man");
per.sayName(); //输出q
要领二(提前先实行一次new):
function WPerson (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
if(typeof this.sayName != "function"){
WPerson.prototype = {
constructor:WPerson,
sayName: function(){
console.log(this.name);
}
};
return new WPerson(name,age,sex); //首次运转时,多挪用一次new
}
}
var per = new WPerson("q", 18, "man");
per.sayName(); //输出q
ES6中的class
class Point{
constructor(x, y) { //相当于java中的组织函数,假如不写默以为空
this.x = x; //x,y定义在对象本身上面
this.y = y;
}
add() { //该要领定义在Point.prototype上
console.log(this.x + this.y);
}
}
var p = new Point(2, 3);
p.add(); //输出5
能够说,class用法就是ES5中动态原型形式。