贵阳市建设局信息管理网站,企业官网免费制作,建一个商业网站要多少钱,天元建设集团有限公司六大板块一、理解对象
1.创建一个对象#xff0c;然后给这个对象新建属性和方法。 ①常见的创建方式
var person new Object(); //创建一个Object 对象person.name XIE; //创建一个name 属性并赋值person.age 20; //创建一个age 属性并赋值person.sayName function () { //创建…一、理解对象
1.创建一个对象然后给这个对象新建属性和方法。 ①常见的创建方式
var person new Object(); //创建一个Object 对象person.name XIE; //创建一个name 属性并赋值person.age 20; //创建一个age 属性并赋值person.sayName function () { //创建一个run()方法并返回值return this.name; //this指的是person本身};
②字面量的形式
var person {name:xie,age:20,job:学生,sayName:function(){return this.name;}
}
2.数据属性 数据属性有4个描述其行为的特性。
特性默认值含义configurabletrue是否可配置表示能否删除属性重新定义能否修改属性的特性能否修改为访问器属性。enumerabletrue是否可枚举writabletrue是否可修改属性值valueundefined属性的数据值
注configurable特性一旦设置为false后则不能再变为true.
var person{};
Object.defineProperty(person,name,{configurable:true,enumerable:true,writable:true,value:xie
})
3.访问器属性
特性默认值含义configurabletrue是否可配置表示能否删除属性重新定义能否修改属性的特性能否修改为访问器属性。enumerabletrue是否可枚举getundefined读取属性时调用setundefined写入属性时调用
二、创建对象
1.工厂模式
function createObject(name, age) { //集中实例化的函数var obj new Object();obj.name name;obj.age age;obj.run function () {return this.name this.age 运行中...;};return obj;
}
var box1 createObject(Lee, 100); //第一个实例
var box2 createObject(Jack, 200); //第二个实例
工厂模式解决了重复实例化的问题但还有一个问题那就是识别问题因为根本无法弄清楚一个对象的类型。
2.构造函数模式
function Person(name,age){this.name name;this.age age;this.run function(){alert(this.name);}
}
var person1 new Person(Lee,100);
var person2 new Person(Jack,200);
使用了构造函数的方法和使用工厂模式的方法他们不同之处如下
构造函数方法没有显示的创建对象(new Object())直接将属性和方法赋值给this 对象没有renturn 语句。
构造函数的方法有一些规范
.函数名和实例化构造名相同且大写(PS非强制但这么写有助于区分构造函数和普通函数)通过构造函数创建对象必须使用new 运算符。
使用new操作符创建实例时执行过程如下
创建一个新对象将构造函数的作用域赋给新对象因此this就指向了这个对象执行构造函数中的代码为这个新对象添加属性返回新对象 使用构造函数的主要问题就是每个方法都要再每个实例上重新创建一遍。通过下面可知不一样:
alert(person1.run person2.run); //false
3.原型模式
我们创建的每个函数都有一个prototype(原型)属性这个属性是一个指针指向一个对象它的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型的好处可以让所有对象实例共享它所包含的属性和方法。也就是说不必在构造函数中定义对象信息而是可以直接将这些信息添加到原型中。
3.1常见的语法
// 原型模式
function Box() {} //声明一个构造函数
Box.prototype.name Lee; //在原型里添加属性
Box.prototype.age 100;
Box.prototype.run function () { //在原型里添加方法return this.name this.age 运行中...;
};
//比较一下原型内的方法地址是否一致
var box1 new Box();
var box2 new Box();
alert(box1.run box2.run); //true方法的引用地址保持一致
为
下面可通过图进一步了解 在原型模式声明中多了两个属性这两个属性都是创建对象时自动生成的。proto属性是实例指向原型对象的一个指针ECMAScript5称这个指针为[[Prototype]],它的作用就是指向构造函数的原型属性constructor。
isPrototypeOf()方法来判断一个对象是否指向了该构造函数的原型
alert(Box.prototype.isPrototypeOf(box1)); //true,只要实例化对象即都会指向
Object.getPrototype()方法返回[[Prototype]]的值。IE9,Firefox3.5,Safari5Opera12 和Chrome支持
alert(Object.getPrototype(box1).name); //Lee
原型模式的执行流程
.先查找构造函数实例里的属性或方法如果有立刻返回如果构造函数实例里没有则去它的原型对象里找如果有就返回
hasOwnProperty()函数判断构造函数的实例中是否有该属性。
alert(box.hasOwnProperty(name)); //实例里有返回true否则返回false
in操作符会在通过对象能够访问给定属性时返回 true无论该属性存在于实例中还是原型中。
alert(name in box); //true存在实例中或原型中
function isProperty(object, property) { //判断原型中是否存在属性return !object.hasOwnProperty(property) (property in object);
}
3.2更简单的原型语法
为了让属性和方法更好的体现封装的效果并且减少不必要的输入原型的创建可以使用字面量的方式
function Box() {};
Box.prototype { //使用字面量的方式name : Lee,age : 100,run : function () {return this.name this.age 运行中...;}
};
使用构造函数创建原型对象和使用字面量创建对象在使用上基本相同但还是有一些区别字面量创建的方式使用constructor 属性不会指向实例而会指向Object构造函数创建的方式则相反。
var box new Box();
alert(box instanceof Box); //true
alert(box instanceof Object); //true
alert(box.constructor Box); //字面量方式返回false否则true
alert(box.constructor Object); //字面量方式返回true否则false
如果想让字面量方式的constructor 指向实例对象可以如下所示
function Box() {};
Box.prototype { //使用字面量的方式constructor : Box, //直接强制指向即可name : Lee,age : 100,run : function () {return this.name this.age 运行中...;}
};
重设constructor会导致它的enumerable特性被修改为true,默认情况下原生的constructor是不可枚举的可使用Object.defineProperty()方法重设构造函数。
Object.defineProperty(Box.prototype,constructor,{enumerable:false,value:Box
});
原型的声明是有先后顺序的所以重写的原型会切断之前的原型。
function Box() {};
Box.prototype { //原型被重写了constructor : Box,name : Lee,age : 100,run : function () {return this.name this.age 运行中...;}
};
Box.prototype {age 200
};
var box new Box(); //在这里声明
alert(box.run()); //erroe,因为box 只是最初声明的原型
3.3原型对象的问题
原型模式创建对象也有自己的缺点它省略了构造函数传参初始化这一过程带来的缺点就是初始化的值都是一致的。而原型最大的缺点就是它最大的优点那就是共享。原型中所有属性是被很多实例共享的共享对于函数非常合适对于包含基本值的属性也还可以。但如果属性包含引用类型就存在一定的问题
function Box() {};
Box.prototype {constructor : Box,name : Lee,age : 100,family : [父亲, 母亲, 妹妹], //添加了一个数组属性run : function () {return this.name this.age this.family;}
};
var box1 new Box();
box1.family.push(哥哥); //在实例中添加哥哥
alert(box1.run());
var box2 new Box();
alert(box2.run()); //共享带来的麻烦也有哥哥了
4.动态原型模式
为了解决构造传参和共享问题可以组合构造函数原型模式即动态原型模式。
function Box(name ,age) { //将所有信息封装到函数体内this.name name; //不共享的使用构造函数形式this.age age;if (typeof this.run ! function) { //仅在第一次调用的初始化Box.prototype.run function () { //共享的使用原型模式return this.name this.age 运行中...;};}
}
var box new Box(Lee, 100);
alert(box.run());
当第一次调用构造函数时run()方法发现不存在然后初始化原型。当第二次调用就不会初始化并且第二次创建新对象原型也不会再初始化了。这样及得到了封装又实现了原型方法共享并且属性都保持独立。 PS使用动态原型模式要注意一点不可以再使用字面量的方式重写原型因为会切断实例和新原型之间的联系。
5.寄生构造函数模式
寄生构造函数其实就是工厂模式构造函数模式。这种模式比较通用但不能确定对象关系。
function myString(string) {var str new String(string);str.addstring function () {return this 被添加了;};return str;
}
var box new myString(Lee); //比直接在引用原型添加要繁琐好多
alert(box.addstring());
使用场景要创建一个具有额外方法的引用类型时。
6.稳妥构造函数模式
在一些安全的环境中比如禁止使用this 和new这里的this 是构造函数里不使用this这里的new 是在外部实例化构造函数时不使用new。
function Box(name , age) {var obj new Object();obj.run function () {return name age 运行中...; //直接打印参数即可};return obj;
}
var box Box(Lee, 100); //直接调用函数
alert(box.run());
PS稳妥构造函数和寄生类似。