您的位置:首页 > Web前端 > JavaScript

Javascript高级程序设计第六七章

2015-07-30 21:28 573 查看
1.目前使用最广泛、认同度最高的一种创建自定义类型的方法

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


2.通过下面的函数可以确定属性存在与对象还是原型中

function hasPrototypeProperty(object, name){     return !object.hasOwnProperty(name) && (name in object)}

3.组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为Javascript中最常用的继承模式。

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;
}

SubType.prototype = new 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


原型链的缺点:

①原先的父类实例属性就顺利成章地变成了现在的原型属性,会被所有子类共享

②没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数(原因是①)

但这些都被借用构造函数所解决

借用构造函数的缺点:方法都在构造函数中定义,因此函数复用无从谈起

原型链的注意点:

①给原型添加方法的代码一定要放在替换原型的语句之后

②不能通过对象字面量创建原型方法,等于改写原型了

4.闭包与变量

闭包:指的是有权访问另一个函数作用域中的变量的函数,常见方式,就是在一个函数内部创建另一个函数

作用域链中的这种配置机智引出了一个值得注意的副作用,即闭包只能取得包含函数中的任何变量的最后一个值。别忘了闭包所保存耳朵是整个变量对象,而不是某个特殊的变量

function createFunctions(){
var result = new Array();

for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}

return result;
}

var funcs = createFunctions();

//every function outputs 10
for (var i=0; i < funcs.length; i++){
document.write(funcs[i]() + "<br />");
}
因为每个函数的作用域中都保存着createFunctions()函数的活动对象,所以它们引用的都是同一个变量i

但是,我们可以通过创建另一个匿名哈数强制让闭包的行为符合预期

function createFunctions(){
var result = new Array();

for (var i=0; i < 10; i++){
result[i] = function(num){
return function(){
return num;
};
}(i);
}

return result;
}

var funcs = createFunctions();

//every function outputs 10
for (var i=0; i < funcs.length; i++){
document.write(funcs[i]() + "<br />");
}
个人认为,因为传递给num的时候,其实就是一个值了,不是变量了

书上:由于函数传递是按值传递的,所以就会将变量i的当前值辅助给参数num,这样一来,result数组中的每个函数都有自己的num变量的一个副本

关于This对象

由于匿名函数的执行环境具有全局性,因此其this对象通常指向window

var name = "The Window";

var object = {
name : "My Object",

getNameFunc : function(){
//var that = this;
return function(){
return that.name;
};
}
};

alert(object.getNameFunc()());  //"The Window"
前面曾经提到,每个函数在被调用时都会自动取得两个特殊变量:this和arguments。内部函数在搜索这两个变量时,只会搜索其活动对象为止(getNameFuc),因此永远不可能直接访问到外部函数中的这两个变量。因此去掉上面的注释就可以了

5.私有变量

严格来讲,Javascript没有私有成员的概念。但任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数的外部访问到这些变量,私有变量包括函数的参数、局部变量和在函数内部定义的其他函数

特权方法:有权访问私有变量和私有函数的公有方法

第一种方法是在构造函数中定义特权方法

function MyObject(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction()
{ return false; }
//特权方法
this.publicMethod = function(){
privateVariable++;
return privateFunction();
};}
利用的也是闭包的原理

第二种方法是在私有作用域中定义私有变量和函数(生成静态私有变量,私有函数)

(function(){

var name = "";

Person = function(value){
name = value;
};

Person.prototype.getName = function(){
return name;
};

Person.prototype.setName = function (value){
name = value;
};
})();

var person1 = new Person("Nicholas");
alert(person1.getName());   //"Nicholas"
person1.setName("Greg");
alert(person1.getName());   //"Greg"

var person2 = new Person("Michael");
alert(person1.getName());   //"Michael"
alert(person2.getName());   //"Michael"


需要注意的是,这个模式在定义构造函数时没有使用函数声明,而是使用函数表达式,函数声明只能创建局部函数。出于同样的原因。我们在声明MyObject时也没使用var关键字,还有需要注意的是私有变量和私有函数是由实例共享的

6.模块模式

模块模式即为单例创建私有变量和特权方法

function BaseComponent(){
}

function OtherComponent(){
}

var application = function(){

//private variables and functions
var components = new Array();

//initialization
components.push(new BaseComponent());

//public interface
return {
getComponentCount : function(){
return components.length;
},

registerComponent : function(component){
if (typeof component == "object"){
components.push(component);
}
}
};
}();

application.registerComponent(new OtherComponent());
alert(application.getComponentCount());  //2
简言之,如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有数据的方法,那么久可以使用模块模式。

增强的模块模式

这种增强的模块模式适合那些单例必须是某种类型的实例,同时还必须添加某些属性和(或)方法对其加以增强的情况。

function BaseComponent(){
}

function OtherComponent(){
}

var application = function(){

//private variables and functions
var components = new Array();

//initialization
components.push(new BaseComponent());

//create a local copy of application
var app = new BaseComponent();

//public interface
app.getComponentCount = function(){
return components.length;
};

app.registerComponent = function(component){
if (typeof component == "object"){
components.push(component);
}
};

//return it
return app;
}();

alert(application instanceof BaseComponent);
application.registerComponent(new OtherComponent());
alert(application.getComponentCount());  //2


a8df
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: