澳门太阳娱乐集团官网-太阳集团太阳娱乐登录

【澳门太阳娱乐集团官网】浅谈 JS 创建对象的
分类:网页制作

浅谈 JS 创立对象的 8 种方式

2015/10/16 · JavaScript · 对象

原稿出处: Tomson   

  • Objct 模式
  • 厂子格局
  • 构造器方式
  • 经过 Function 对象达成
  • prototype 模式
  • 布局器与原型格局的插花情势
  • 动态原型格局
  • 混合工厂格局

1.Object 模式

var o1 = {};//字面量的表现形式
var o2 = new Object;
var o3 = new Object();
var o4 = new Object(null);
var o5 = new Object(undefined);
var o6 = Object.create(Object.prototype);//等价于 var o = {};//即以 Object.prototype 对象为一个原型模板,新建一个以这个原型模板为原型的对象
//上面6种都是一样
//区别
var o7 = Object.create(null);//创建一个原型为 null 的对象

JS成立对象的三种情势及分析相比

1.Object 模式

JavaScript

var o1 = {};//字面量的表现情势 var o2 = new Object; var o3 = new Object(卡塔尔国; var o4 = new Object(null卡塔尔(قطر‎; var o5 = new Object(undefined卡塔尔国; var o6 = Object.create(Object.prototype卡塔尔;//等价于 var o = {};//即以 Object.prototype 对象为贰个原型模板,新建三个以这几个原型模板为原型的目标//分裂 var o7 = Object.create(null卡塔尔(قطر‎;//成立几个原型为 null 的靶子

1
2
3
4
5
6
7
8
var o1 = {};//字面量的表现形式
var o2 = new Object;
var o3 = new Object();
var o4 = new Object(null);
var o5 = new Object(undefined);
var o6 = Object.create(Object.prototype);//等价于 var o = {};//即以 Object.prototype 对象为一个原型模板,新建一个以这个原型模板为原型的对象
//区别
var o7 = Object.create(null);//创建一个原型为 null 的对象

在 chrome 里查看各样新建对象的分别:
澳门太阳娱乐集团官网 1

能够寓前段时间6种情势创设出来的靶子都以均等的,第多种差异点在于其固然也为 Object 对象但其无其余性质(饱含未有别的能够世襲的属性,因为成立的时候未有一点名其原型卡塔尔

2.工厂方式

//工厂方法1 通过一个方法来创建对象 利用 arguments 对象获取参数设置属性(参数不直观,容易出现问题)
function createCar(){
    var oTemp = new Object();
    oTemp.name = arguments[0];//直接给对象添加属性,每个对象都有直接的属性
    oTemp.age = arguments[1];
    oTemp.showName = function () {
        alert(this.name);
    };//每个对象都有一个 showName 方法版本
    return oTemp;
}
createCar("tom").showName();//在 JS 中没有传递的实参,实际形参值为 undefined(这里的 age 为 undefined)
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

//工厂方法2 通过传参设置属性(参数直观明了)
function createCar(name,age){
    var oTemp = new Object();
    oTemp.name = name;//直接给对象添加属性,每个对象都有直接的属性
    oTemp.age = age;
    oTemp.showName = function () {
        alert(this.name);
    };//每个对象都有一个 showName 方法版本
    return oTemp;
}
createCar("tom").showName();
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

工厂格局

function createPerson(name, age, job){
    //创建对象
    var o = new Object();
    //添加属性
    o.name = name;
    o.age = age;
    o.job = job;
    //添加方法
    o.sayName = function(){
        console.log(this.name);
    };
    //返回对象
    return o;
}

实例化:

var person1 = createPerson('smith', 25, 'coder');

缺欠:未有解决对象的辨认问题.

2.工厂形式

JavaScript

//工厂方法1 通过一个艺术来创设对象 利用 arguments 对象获得参数设置属性(参数不直观,轻易现身难题卡塔尔 function createCar(卡塔尔(قطر‎{ var oTemp = new Object(卡塔尔国; oTemp.name = arguments[0];//直接给指标加多属性,各种对象都有一向的品质 oTemp.age = arguments[1]; oTemp.showName = function (卡塔尔(英语:State of Qatar) { alert(this.name卡塔尔; };//每种对象都有叁个 showName 方法版本 return oTemp; } createCar("tom"卡塔尔(قطر‎.showName(卡塔尔;//在 JS 中绝非传递的实参,实际形参值为 undefined(这里的 age 为 undefined卡塔尔(قطر‎ createCar("tim",80卡塔尔(قطر‎.showName(卡塔尔国; alert(createCar("tom"卡塔尔 instanceof Object卡塔尔(英语:State of Qatar);//true 决断指标是或不是 Object 类或子类

1
2
3
4
5
6
7
8
9
10
11
12
13
//工厂方法1 通过一个方法来创建对象 利用 arguments 对象获取参数设置属性(参数不直观,容易出现问题)
function createCar(){
    var oTemp = new Object();
    oTemp.name = arguments[0];//直接给对象添加属性,每个对象都有直接的属性
    oTemp.age = arguments[1];
    oTemp.showName = function () {
        alert(this.name);
    };//每个对象都有一个 showName 方法版本
    return oTemp;
}
createCar("tom").showName();//在 JS 中没有传递的实参,实际形参值为 undefined(这里的 age 为 undefined)
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

JavaScript

//工厂方法2 由此传参设置属性(参数直观明了卡塔尔国 function createCar(name,age卡塔尔(英语:State of Qatar){ var oTemp = new Object(卡塔尔(英语:State of Qatar); oTemp.name = name;//直接给目的增添属性,每一个对象都有直接的天性 oTemp.age = age; oTemp.showName = function (卡塔尔 { alert(this.name卡塔尔国; };//种种对象都有贰个showName 方法版本 return oTemp; } createCar("tom"卡塔尔(قطر‎.showName(卡塔尔国; createCar("tim",80卡塔尔.showName(卡塔尔; alert(createCar("tom"卡塔尔 instanceof Object卡塔尔国;//true 判断目的是或不是 Object 类或子类

1
2
3
4
5
6
7
8
9
10
11
12
13
//工厂方法2 通过传参设置属性(参数直观明了)
function createCar(name,age){
    var oTemp = new Object();
    oTemp.name = name;//直接给对象添加属性,每个对象都有直接的属性
    oTemp.age = age;
    oTemp.showName = function () {
        alert(this.name);
    };//每个对象都有一个 showName 方法版本
    return oTemp;
}
createCar("tom").showName();
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

3.布局器形式

//构造器方法1
function Car(sColor,iDoors){  //声明为构造器时需要将函数名首字母大写
    this.color = sColor;      //构造器内直接声明属性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };//每个 Car 对象都有自己的 showColor方法版本
    this.showDoor = function () {
        return this.doors;
    }
}

选拔形式1的难点很扎眼,不能是 showDoor 方法重用,每一遍新建三个目的将要在堆里新开垦一片内部存款和储蓄器空间.纠正如下

//构造器方法2
function showDoor(){      //定义一个全局的 Function 对象
    return this.doors;
}

function Car(sColor,iDoors){//构造器
    this.color = sColor;      //构造器内直接声明属性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };
    this.showDoor = showDoor();//每个 Car 对象共享同一个 showDoor 方法版本(方法有自己的作用域,不用担心变量被共享)
}

alert(new Car("red",2).showColor());//通过构造器创建一个对象并调用其对象方法

布局函数方式

function Person(name, age, job){    //Person也是普通的函数, 但便于与普通函数区分, 通常将构造函数首字母大写
    //添加属性
    this.name = name;
    this.age = age;
    this.job = job;
    //添加方法
    this.sayName = function(){
        console.log(this.name);
    };
}

透过比较工厂方式大家发掘:

  1. 并未有显得创立对象;
  2. 直白将质量和方法赋给了this对象,this就是new出来的指标;
  3. 没有return语句.

实例化:

var person1 = new Person('smith', 25, 'coder');

看清实例类型:

console.log(person1.constructor === Person);   //true
console.log(person1 instanceof Person);        //true
console.log(person1 instanceof Object);        //true

澳门太阳娱乐集团官网,优点: 创设自定义的构造函数能够将实例标志为生龙活虎种特定的花色

缺欠: 每一种方法都要在每一种实例上再也成立贰回, 不可能代码共用.

3.构造器情势

JavaScript

//布局器方法1 function Car(sColor,iDoors卡塔尔国{ //评释为组织器时必要将函数名首字母大写 this.color = sColor; //布局器内直接表明属性 this.doors = iDoors; this.showColor = function(卡塔尔(英语:State of Qatar){ return this.color; };//每种 Car 对象都有温馨的 showColor方法版本 this.showDoor = function (卡塔尔(英语:State of Qatar) { return this.doors; } }

1
2
3
4
5
6
7
8
9
10
11
//构造器方法1
function Car(sColor,iDoors){  //声明为构造器时需要将函数名首字母大写
    this.color = sColor;      //构造器内直接声明属性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };//每个 Car 对象都有自己的 showColor方法版本
    this.showDoor = function () {
        return this.doors;
    }
}

运用办法1的标题很确定,无法是 showDoor 方法重用,每一次新建一个对象将要要堆里新开垦生机勃勃篇空间.校订如下

JavaScript

//布局器方法2 function showDoor(卡塔尔国{ //定义一个大局的 Function 对象 return this.doors; } function Car(sColor,iDoors卡塔尔(قطر‎{//结构器 this.color = sColor; //结构器内直接证明属性 this.doors = iDoors; this.showColor = function(卡塔尔(英语:State of Qatar){ return this.color; }; this.showDoor = showDoor(卡塔尔(英语:State of Qatar);//每一种 Car 对象共享同二个 showDoor 方法版本(方法有自身的作用域,不用操心变量被分享卡塔尔国} alert(new Car("red",2卡塔尔(英语:State of Qatar).showColor(卡塔尔(英语:State of Qatar)卡塔尔国;//通过布局器创制八个目的并调用其目的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//构造器方法2
function showDoor(){      //定义一个全局的 Function 对象
    return this.doors;
}
 
function Car(sColor,iDoors){//构造器
    this.color = sColor;      //构造器内直接声明属性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };
    this.showDoor = showDoor();//每个 Car 对象共享同一个 showDoor 方法版本(方法有自己的作用域,不用担心变量被共享)
}
 
alert(new Car("red",2).showColor());//通过构造器创建一个对象并调用其对象方法

地方现身的主题素材正是语义缺乏湮灭,显示不出类的封装性,改进为 prototype 形式

4.由此Function对象完毕创造对象

作者们驾驭每声美素佳儿个函数实际是创建了四个Function 实例 JS 函数.

function function_name(param1,param2){alert(param1);}
//等价于
var function_name = new Function("param1","pram2","alert(param1);");

var Car2 = new Function("sColor","iDoors",
         "this.color = sColor;"+
         "this.doors = iDoors;"+
         "this.showColor = function(){ return this.color; }"
);
alert(new Car2("blue",3).showColor());

原型方式

function Person(){}

//Person.prototype为原型对象,每个构造函数的protot属性指向其对应的原型对象,以下为原型对象添加属性和方法
Person.prototype.name = 'smith';
Person.prototype.age = 25;
Person.prototype.job = 'coder';
Person.prototype.sayName = function(){
    console.log(this.name);
}

实例化:

var person1 = new Person();

赢得原型对象:

console.log(Object.getPrototypeOf(person1) === Person.prototype);   //true

判别原型对象:

console.log(Person.prototype isPrototypeOf(person1))    //true

若为实例增加的习性或方法时与原型对象里的特性或措施后生可畏致, 增添的属性或方法会屏蔽原型对象中的那么些属性或措施

function Person(){}

Person.prototype.name = 'smith';
Person.prototype.age = 25;
Person.prototype.job = 'coder';
Person.prototype.sayName = function(){
    console.log(this.name);
};

var person1 = new Person();
var person2 = new Person();

person1.name = 'Lihua';
console.log(person1.name)   //'Lihua'
console.log(person2.name)   //'smith'

因此上述结果开掘: person1.name属性屏蔽了原型对象里的name属性, 阻止了拜望原型中的那几个属性, 使用delete操作符删除实例属性后, 能够重新访谈原型中的属性

function Person(){}
Person.prototype.name= 'smith';
Person.prototype.age = '25';
Person.prototype.job = 'coder';
Person.prototype.sayName = function(){
    console.log(this.name);
}

var person1 = new Person();
var person2 = new Person();

person1.name = 'Lihua';
console.log(person1.sayName());     //Lihua
console.log(person2.sayName());     //smith

delete person1.name;
console.log(person1.sayName());     //smith

delete Object.getPrototypeOf(person1).name;     //删除原型对象的name属性
console.log(person1.sayName());     //undefined
console.log(person2.sayName());     //undefined

认清属性是还是不是存在于实例中:

person1.name = 'Lihua';
console.log(person1.hasOwnProperty('name'))     //ture

4.经过Function对象实现创造对象

咱俩理解每声澳优个函数实际是创设了三个Function 实例 JS 函数.

JavaScript

function function_name(param1,param2){alert(param1);} //等价于 var function_name = new Function("param1","pram2","alert(param1);");

1
2
3
function function_name(param1,param2){alert(param1);}
//等价于
var function_name = new Function("param1","pram2","alert(param1);");

JavaScript

var Car2 = new Function("sColor","iDoors", "this.color = sColor;"+ "this.doors = iDoors;"+ "this.showColor = function(){ return this.color; }" ); alert(new Car2("blue",3).showColor());

1
2
3
4
5
6
var Car2 = new Function("sColor","iDoors",
         "this.color = sColor;"+
         "this.doors = iDoors;"+
         "this.showColor = function(){ return this.color; }"
);
alert(new Car2("blue",3).showColor());

5.prototype模式

  • 类经过 prototype 属性增添的品质与方式都以绑定在此个类的 prototype 域(实际为一个 Prototype 对象卡塔尔中,绑定到那几个域中的属性与方法独有多个本子,只会成立三回.

  • 类的实例对象足以一贯像调用自身的习性相同调用该类的 prototype 域中的属性与措施,类能够经过调用 prototype 属性来直接调用prototype 域内的属性与方法.

留意:通过类实例化出指标后对象内无 prototype 属性,但指标可一直像访谈属性相符的访问类的 prototype 域的内容,实例对象有个村办属性proto,proto性格内含有类的 prototype 域内的品质与格局

方法1
function Car3(){}//用空构造函数设置类名
Car3.prototype.color = "blue";//每个对象都共享相同属性
Car3.prototype.doors = 3;
Car3.prototype.drivers = new Array("Mike","John");
Car3.prototype.showColor = function(){
    alert(this.color);
};//每个对象共享一个方法版本,省内存。

var car3_1 = new Car3();
var car3_2 = new Car3();

alert(car3_1.color);//blue
alert(car3_2.color);//blue
alert(Car3.prototype.color);//blue

car3_1.drivers.push("Bill");
alert(car3_1.drivers);//"Mike","John","Bill"
alert(car3_2.drivers);//"Mike","John","Bill"
alert(Car3.prototype.drivers);//"Mike","John","Bill"

//直接修改实例对象的属性,解析器会先去找实例对象是否有这个属性(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 属性,而是直接查看这个实例是否有对应的属性(与_proto_同级))
//如果没有则直接给这个实例对象添加该属性,但不会修改类的prototype域的同名属性,既实例对象的_proto_属性内的那些类 prototype 域属性不会被修改
car3_1.color = "red";//car3_1对象内无名为 color 的对象属性,故将该属性添加到该对象上

//解析器对实例对象读取属性值的时候会先查找该实例有无同名的直接属性
//如果没有,则查找__proto__属性内保存的那些 当前类的 prototype 域的属性
//有就返回,无则继续查找是否有原型链中的对应的方法属性
//有就返回,无则返回undefined
alert(car3_1.color);//red
alert(car3_2.color);//blue
alert(car3_2.color2);//undefined

//直接修改类的 prototype 域内的属性,不会影响该类的实例对象的对象属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容)
Car3.prototype.color = "black";
alert(car3_1.color);//red 该对象有同名的直接属性,故不会去_proto_属性内查找类的 prototype 域的属性
alert(car3_2.color);//black 受影响

//直接修改实例对象的方法,解析器会先去找实例对象是否有这个方法(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 域的方法,而是直接查看这个实例是否有对应的方法(与_proto_同级))
//如果没有则直接给这个实例对象添加该方法,但不会修改类的prototype域的同名方法,既实例对象的_proto_属性内的那些类 prototype 域方法不会被修改
//car3_1对象内无名为 showColor 的对象方法属性,故将该方法属性添加到该对象上
car3_1.showColor = function () {
    alert("new function");
}
//解析器对实例对象调用方法属性的时候会先查找该实例有无同名的直接方法属性
//如果没有,则查找_proto_属性内保存的那些 当前类的 prototype 域的方法属性
//有就返回,无则继续查找是否有原型链中的对应的方法属性
//找到就返回,无则报错

car3_1.showColor();//new function
car3_2.showColor();//blue
car3_1.abcd();//直接报错

//直接修改类的 prototype 域内的方法属性,不会影响该类的实例对象的方法属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容)
Car3.prototype.showColor = function () {
    alert("second function");
}
car3_1.showColor();//new function 该对象有同名的方法属性,故不会去_proto_属性内查找类的 prototype 域的方法属性
car3_2.showColor();//second function 受影响

能够看见使用该办法固然说打打裁减了内部存款和储蓄器的浪费,但依然有标题,某些对象的性质生龙活虎旦改变,全体由此类实例化得到的靶子的proto内属性值也会随之变(实为引用卡塔尔(قطر‎,改良如下

原型的动态性

对原型对象所做的任何改动能够马上从实例上呈现出来, 尽管是先实例化后改革原型对象也是这么

var friend = new Person();
Person.prototype.sayHi = function(){
    console.log('hi');
}

friend.sayHi()      //依然能够执行

JS高程写到:

固然对原型对象所做的别样退换能够立即在享有实例中显示出来, 但重写整个原型对象情状照旧不一样等的, 调用布局函数时会为实例增加三个针对最先原型的[[prototype]]指南针, 把原型修改为其余贰个对象就砍断了构造函数与最先原型之间的联络

function Person(){}
var friend = new Person();

Person.prototype = {
    constructor: Person,
    name: 'Lihua',
    job: 'student',
    sayName: function(){
        console.log(this.name);
    }
};

friend.sayName();   //error

但感到JS高程这种说法有些欠妥, 举个例子:

function Person(){}
Person.prototype.job = 'coder';
Person.prototype.sayJob = function(){
    console.log(this.job);
}
var friend = new Person();

Person.prototype = {
    constructor: Person,
    name: 'Lihua',
    job: 'student',
    sayName: function(){
        console.log(this.name);
    }
};
var person = new Person();

person.sayName();   //Lihua
friend.sayJob();    //coder
// person.sayJob();    error

自己的掌握是:

  1. 原型是生机勃勃种动态动态的关联,增多叁个新的质量或艺术到原型中时,该属性或方法会马上对富有基于该原型创制的对象可知,哪怕是修正原型以前创制的目的;
  2. 将原型重写为此外一个对象后, 会影响重写后实例获得的目的, 割断了结构函数与最早原型之间的调换; 对于重写在此以前已经实例化的对象未有影响, 因为那么些目的里早就保存了一个[[prototype]]指南针, 该指针指向重写以前的原型对象;

5.prototype模式

  • 类经过 prototype 属性加多的性质与办法都以绑定在这里个类的 prototype 域(实际为一个 Prototype 对象卡塔尔国中,绑定到那个域中的属性与艺术唯有五个版本,只会创制一回.
  • 类的实例对象足以一贯像调用本人的质量相似调用该类的 prototype 域中的属性与方法,类能够经过调用 prototype 属性来直接调用prototype 域内的习性与方法.

小心:通过类实例化出指标后对象内无 prototype 属性,但指标可直接像访谈属性雷同的访问类的 prototype 域的剧情,实例对象有个个体属性__proto__,__proto__品质内含有类的 prototype 域内的性情与艺术

JavaScript

艺术1 function Car3(卡塔尔{}//用空布局函数设置类名 Car3.prototype.color = "blue";//每种对象都分享相像属性 Car3.prototype.doors = 3; Car3.prototype.drivers = new Array("Mike","John"卡塔尔(英语:State of Qatar); Car3.prototype.showColor = function(卡塔尔(英语:State of Qatar){ alert(this.color卡塔尔; };//每一个对象分享三个主意版本,省外部存款和储蓄器。 var car3_1 = new Car3(); var car3_2 = new Car3(); alert(car3_1.color);//blue alert(car3_2.color);//blue alert(Car3.prototype.color);//blue car3_1.drivers.push("Bill"); alert(car3_1.drivers);//"Mike","John","Bill" alert(car3_2.drivers卡塔尔(قطر‎;//"Mike","John","Bill" alert(Car3.prototype.drivers卡塔尔;//"迈克","John","Bill" //直接改良实例对象的性质,拆解解析器会先去找实例对象是或不是有这几个性格(不会去找实例对象的 _proto_ 属性内的那么些类的 prototype 属性,而是一向查看这一个实例是或不是有对应的脾气(与_proto_同级卡塔尔(قطر‎)//若无则直接给那些实例对象增多该属性,但不会改过类的prototype域的同名属性,既实例对象的_proto_属性内的那几个类 prototype 域属性不会被改正 car3_1.color = "red";//car3_1对象内无名氏叫color 的指标属性,故将该属性加多到该对象上 //剖析器对实例对象读取属性值的时候会先查找该实例有无同名的一向属性 //若无,则查找__proto__属性内保存的那么些 当前类的 prototype 域的性子 //有就赶回,无则继续寻觅是还是不是有原型链中的对应的办法属性 //有就回到,无则重返undefined alert(car3_1.color);//red alert(car3_2.color);//blue alert(car3_2.color2卡塔尔国;//undefined //直接校勘类的 prototype 域内的品质,不会潜移暗化该类的实例对象的目的属性,但会影响实例对象的_proto_属性(_proto_质量内部存款和储蓄器放的是类的 prototype 域的始末卡塔尔(قطر‎ Car3.prototype.color = "black"; alert(car3_1.color卡塔尔;//red 该对象有同名的第一手属性,故不会去_proto_天性内查找类的 prototype 域的习性 alert(car3_2.color卡塔尔(قطر‎;//black 受影响 //直接改革实例对象的法子,深入分析器会先去找实例对象是否有这么些艺术(不会去找实例对象的 _proto_ 属性内的那么些类的 prototype 域的措施,而是径直查看这么些实例是还是不是有对应的艺术(与_proto_同级卡塔尔(英语:State of Qatar))//若无则直接给那些实例对象增加该办法,但不会改善类的prototype域的同名方法,既实例对象的_proto_属性内的那个类 prototype 域方法不会被校正 //car3_1指标内佚名称叫 showColor 的对象方法属性,故将该措施属性增添到该指标上 car3_1.showColor = function (卡塔尔 { alert("new function"卡塔尔; } //深入深入分析器对实例对象调用方法属性的时候会先查找该实例有无同名的一向情势属性 //若无,则查找_proto_属性内保存的那么些 当前类的 prototype 域的法子属性 //有就回到,无则持续查找是不是有原型链中的呼应的点子属性 //找到就回来,无则报错 car3_1.showColor();//new function car3_2.showColor();//blue car3_1.abcd(卡塔尔(قطر‎;//直接报错 //直接改革类的 prototype 域内的不二秘技属性,不会影响该类的实例对象的情势属性,但会潜濡默化实例对象的_proto_属性(_proto_品质内部存款和储蓄器放的是类的 prototype 域的内容卡塔尔(قطر‎ Car3.prototype.showColor = function (卡塔尔(قطر‎ { alert("second function"卡塔尔; } car3_1.showColor(卡塔尔(قطر‎;//new function 该对象有同名的艺术属性,故不会去_proto_属性内查找类的 prototype 域的法子属性 car3_2.showColor();//second function 受影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
方法1
function Car3(){}//用空构造函数设置类名
Car3.prototype.color = "blue";//每个对象都共享相同属性
Car3.prototype.doors = 3;
Car3.prototype.drivers = new Array("Mike","John");
Car3.prototype.showColor = function(){
    alert(this.color);
};//每个对象共享一个方法版本,省内存。
 
var car3_1 = new Car3();
var car3_2 = new Car3();
 
alert(car3_1.color);//blue
alert(car3_2.color);//blue
alert(Car3.prototype.color);//blue
 
car3_1.drivers.push("Bill");
alert(car3_1.drivers);//"Mike","John","Bill"
alert(car3_2.drivers);//"Mike","John","Bill"
alert(Car3.prototype.drivers);//"Mike","John","Bill"
 
//直接修改实例对象的属性,解析器会先去找实例对象是否有这个属性(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 属性,而是直接查看这个实例是否有对应的属性(与_proto_同级))
//如果没有则直接给这个实例对象添加该属性,但不会修改类的prototype域的同名属性,既实例对象的_proto_属性内的那些类 prototype 域属性不会被修改
car3_1.color = "red";//car3_1对象内无名为 color 的对象属性,故将该属性添加到该对象上
 
//解析器对实例对象读取属性值的时候会先查找该实例有无同名的直接属性
//如果没有,则查找__proto__属性内保存的那些 当前类的 prototype 域的属性
//有就返回,无则继续查找是否有原型链中的对应的方法属性
//有就返回,无则返回undefined
alert(car3_1.color);//red
alert(car3_2.color);//blue
alert(car3_2.color2);//undefined
 
//直接修改类的 prototype 域内的属性,不会影响该类的实例对象的对象属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容)
Car3.prototype.color = "black";
alert(car3_1.color);//red 该对象有同名的直接属性,故不会去_proto_属性内查找类的 prototype 域的属性
alert(car3_2.color);//black 受影响
 
//直接修改实例对象的方法,解析器会先去找实例对象是否有这个方法(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 域的方法,而是直接查看这个实例是否有对应的方法(与_proto_同级))
//如果没有则直接给这个实例对象添加该方法,但不会修改类的prototype域的同名方法,既实例对象的_proto_属性内的那些类 prototype 域方法不会被修改
//car3_1对象内无名为 showColor 的对象方法属性,故将该方法属性添加到该对象上
car3_1.showColor = function () {
    alert("new function");
}
//解析器对实例对象调用方法属性的时候会先查找该实例有无同名的直接方法属性
//如果没有,则查找_proto_属性内保存的那些 当前类的 prototype 域的方法属性
//有就返回,无则继续查找是否有原型链中的对应的方法属性
//找到就返回,无则报错
 
car3_1.showColor();//new function
car3_2.showColor();//blue
car3_1.abcd();//直接报错
 
//直接修改类的 prototype 域内的方法属性,不会影响该类的实例对象的方法属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容)
Car3.prototype.showColor = function () {
    alert("second function");
}
car3_1.showColor();//new function 该对象有同名的方法属性,故不会去_proto_属性内查找类的 prototype 域的方法属性
car3_2.showColor();//second function 受影响

能够看见使用该格局固然说打打裁减了内存的浪费,但依旧极度,有些对象的性质生机勃勃旦改换,所有因而类实例化获得的靶子的__proto__内属性值也会跟着变(实为援用卡塔尔国,校正如下

6.布局器方式与原型方式的叶影参差格局

//每个对象有专属的属性不会与其他对象共享
function Car4(sColor,iDoors){
    this._color = sColor;//私有属性变量名称头加下划线标识
    this._doors = iDoors;
    this.drivers = new Array("Mike","John");//公有属性标识
}
//所有对象共享一个方法版本,减少内存浪费
Car4.prototype.showColor = function () {
    alert(this._color);
};

var car4_1 = new Car4("red",4);
var car4_2 = new Car4("blue",3);

car4_1.drivers.push("Bill");

alert(car4_1.drivers);//"Mike","John","Bill"
alert(car4_2.drivers);//"Mike","John"

原型对象的主题素材

固然能够在实例上增多二个同名属性进而隐蔽那么些无需分享的性质, 但是对于富含引用类型的值的习性来讲, 难题就相比出色.

function Person(){}

Person.prototype = {
    constructor: Person,
    name: 'smith',
    job: 'coder',
    friends: ['shelby', 'court'],
    sayName: function(){
        console.log(this.name);
    }
};

var person1 = new Person();
var person2 = new Person();

person1.friends.push('van');

console.log(person1.friends);                       //'shelby,court,van'
console.log(person2.friends);                       //'shelby,court,van'
console.log(person1.friends === person2.friends);   //true

在此种场所下,person1person2friends质量完全雷同, 那不相符常识(壹人的相恋的人怎么大概和其它一位的爱侣完全雷同呢?卡塔尔国.

可取: 全数实例分享原型对象的属性和情势

症结: 原型方式的最大主题素材相比以上所述, 无法屏蔽原型中数据类型为援引类型的属性

6.布局器格局与原型方式的叶影参差情势

JavaScript

//每一个对象有专项的性质不会与其余对象共享 function Car4(sColor,iDoors卡塔尔{ this._color = sColor;//私有性能变量名称头加下划线标记 this._doors = iDoors; this.drivers = new Array("Mike","John"卡塔尔;//公有属性标志 } //全体对象分享八个主意版本,减弱内部存款和储蓄器浪费 Car4.prototype.showColor = function (卡塔尔(英语:State of Qatar) { alert(this._color); }; var car4_1 = new Car4("red",4); var car4_2 = new Car4("blue",3); car4_1.drivers.push("Bill"); alert(car4_1.drivers);//"Mike","John","Bill" alert(car4_2.drivers);//"Mike","John"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//每个对象有专属的属性不会与其他对象共享
function Car4(sColor,iDoors){
    this._color = sColor;//私有属性变量名称头加下划线标识
    this._doors = iDoors;
    this.drivers = new Array("Mike","John");//公有属性标识
}
//所有对象共享一个方法版本,减少内存浪费
Car4.prototype.showColor = function () {
    alert(this._color);
};
 
var car4_1 = new Car4("red",4);
var car4_2 = new Car4("blue",3);
 
car4_1.drivers.push("Bill");
 
alert(car4_1.drivers);//"Mike","John","Bill"
alert(car4_2.drivers);//"Mike","John"

那也是常用的成立对象形式之豆蔻年华

7.动态原型情势

function Car5(sColor,iDoors,iMpg){
    this.color = sColor;
    this.doors = iDoors;
    this.mpg = iMpg;
    this.drivers = new Array("Mike","John");

    //使用标志(_initialized)来判断是否已给原型赋予了任何方法,保证方法永远只被创建并赋值一次
    if(typeof Car5._initialized == "undefined"){//因为这里的标记是附加在类上,故如果后期直接对其进行修改,还是有可能出现再次创建的情况
        Car5.prototype.showColor = function () {//为Car5添加一个存放在 prototype 域的方法
            alert(this.color);
        };
        Car5._initialized = true;//设置一个静态属性
    }
}
var car5_1 = new Car5("red",3,25);
var car5_2 = new Car5("red",3,25);

布局函数格局+原型形式

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('smith', 25, 'coder');
var person2 = new Person('Lihua', 28, 'worker');

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

构造函数方式+原型方式结合了布局函数情势和原型方式的独特之处, 将必要实例单独具有的属性放到构造函数里, 将急需实例分享的主意放到原型里, 这种方式是如今使用最分布和认可度最高的生龙活虎种创设自定义类型的方法.

7.动态原型形式

JavaScript

function Car5(sColor,iDoors,iMpg卡塔尔(英语:State of Qatar){ this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.drivers = new Array("Mike","John"卡塔尔; //使用标识(_initialized卡塔尔来剖断是不是已给原型授予了别的方式,保障措施永恒只被创制并赋值一次if(typeof Car5._initialized == "undefined"卡塔尔(英语:State of Qatar){//因为此处的符号是增大在类上,故假设前时期接对其实行纠正,依旧有不小可能率现身重复创设的场合Car5.prototype.showColor = function (卡塔尔(قطر‎ {//为Car5增多叁个寄放在 prototype 域的措施 alert(this.color卡塔尔国; }; Car5._initialized = true;//设置四个静态属性 } } var car5_1 = new Car5("red",3,25); var car5_2 = new Car5("red",3,25);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Car5(sColor,iDoors,iMpg){
    this.color = sColor;
    this.doors = iDoors;
    this.mpg = iMpg;
    this.drivers = new Array("Mike","John");
 
    //使用标志(_initialized)来判断是否已给原型赋予了任何方法,保证方法永远只被创建并赋值一次
    if(typeof Car5._initialized == "undefined"){//因为这里的标记是附加在类上,故如果后期直接对其进行修改,还是有可能出现再次创建的情况
        Car5.prototype.showColor = function () {//为Car5添加一个存放在 prototype 域的方法
            alert(this.color);
        };
        Car5._initialized = true;//设置一个静态属性
    }
}
var car5_1 = new Car5("red",3,25);
var car5_2 = new Car5("red",3,25);

这种情势使得定义类像强类型语言比方 java 等语言的概念情势

8.混合工厂情势

function Car6(){
    var oTempCar = new Object;
    oTempCar.color = "blue";
    oTempCar.doors = 4;
    oTempCar.showColor = function () {
        alert(this.color);
    };
    return oTempCar;
}
var car6 = new Car6();

由于在 Car6(卡塔尔结构函数内部调用了 new 运算符,所以将忽视第二个 new 运算符(坐落于布局函数之外卡塔尔国,
在布局函数内部成立的靶子被传送回变量car6,这种方式在指标方法的内处方面与卓绝格局(工厂方法卡塔尔有着形似的难点.应尽量防止

动态原型情势

function Person(name, age, job){
    //属性
    this.name = name;
    this.age = age;
    this.job = job;

    //方法
    if(typeof this.sayName != 'function'){  //在sayName方法不存在的情况下,将其添加到原型中
        Person.prototype.sayName = function(){
            console.log(this.name);
        };
    }
}

var friend = new Person('smith', 25, 'coder');
friend.sayName();   //smith

动态原型方式把富有音信都打包到了布局函数中, 通过在布局函数中初始化原型(可选卡塔尔国, 保持了而且使用布局函数和原型的优点.

8.混合工厂格局

JavaScript

function Car6(){ var oTempCar = new Object; oTempCar.color = "blue"; oTempCar.doors = 4; oTempCar.showColor = function () { alert(this.color); }; return oTempCar; } var car6 = new Car6();

1
2
3
4
5
6
7
8
9
10
function Car6(){
    var oTempCar = new Object;
    oTempCar.color = "blue";
    oTempCar.doors = 4;
    oTempCar.showColor = function () {
        alert(this.color);
    };
    return oTempCar;
}
var car6 = new Car6();

鉴于在 Car6(卡塔尔国构造函数内部调用了 new 运算符,所以将忽视第1个 new 运算符(坐落于布局函数之外卡塔尔国,
在构造函数内部创设的靶子被传送回变量car6,这种办法在对象方法的内处方面与精华方式(工厂方法卡塔尔有着相符的难题.应尽量制止

1 赞 3 收藏 评论

澳门太阳娱乐集团官网 2

寄生构造函数形式

function createPerson(name, age, job){
    //创建对象
    var o = new Object();
    //添加属性
    o.name = name;
    o.age = age;
    o.job = job;
    //添加方法
    o.sayName = function(){
        console.log(this.name);
    };
    //返回对象
    return o;
}

var person1 = new Person('smith', 25, 'coder');
friend.sayName();   //'smith

寄生结构函数格局除了调用方式与工厂格局差异外new Person('smith', 25, 'coder'),别的完全相符, 通过在结构函数末尾增加return语句, 重写了调用布局函数时重回的对象

寄生构造函数方式相符在极其规境况下为对象创建布局函数. 因为不引入在产物化的次序中期维改革原生对象的原型, 但在某个场馆下又真的需求创制三个独具额外措施的原生对象:

function SpecialArray(){
    //创建数组
    var values = new Array();
    //添加值
    values.push.apply(values, arguments);
    //添加方法
    values.toPipedString = function(){
        return this.join('|');
    }

    //返回具有额外方法的数组
    return values;
}

var colors = new SpecialArray('red', 'blue', 'green');
console.log(colors.toPipedString()) //'red|blue|green'

短处: 再次来到的对象与布局函数或与布局函数的原型属性之间从未关联, 因为return语木正写了调用构造函数时回来的靶子, 也等于结构函数再次回到的对象与在构造函数外界创设的目的未有何两样, 不能够依附instanceof操作符分明目的类型

稳当结构函数形式

function Person(name, age, job){
    //创建要返回的对象
    var o = new Object();

    //这里定义私有变量和函数

    //添加方法
    o.sayName = function(){
        console.log(name);
    }

    //返回对象
    return o;
}

本文由澳门太阳娱乐集团官网发布于网页制作,转载请注明出处:【澳门太阳娱乐集团官网】浅谈 JS 创建对象的

上一篇:没有了 下一篇:澳门太阳娱乐集团官网JavaScript 创建对象的七种方
猜你喜欢
热门排行
精彩图文