天天看点

JavaScript高级程序设计第六章

ECMAScript有两种属性:数据属性和访问器属性

修改对象的属性的特性

var person = {};

Object.defineProperty(person,“name”,{

writeable:false,

value:“lala”

});

alert(person.name); //lala

person.name = “haha”;

alert(person.name); //lala

这个是无法修改name的值

var person = {};

Object.defineProperty(person,“name”,{

configurable:false,

value:“lala”

});

alert(person.name); //lala

delete person.name;

alert(person.name); //lala

访问器属性

例子:

var book = {

year :2018,

edition :1

};

Object.defineProperty(book,“year”,{

get:function(){

return this.year;

},

set:function(newValue){

this.year = newValue;

this.edition += newValue-2019;

}

});

book.year = 2020;

alert(book.edition); //2

只指定getter意味着属性不能写

只指定setter,意味着属性不能读

定义多个属性:

例子:

var book = {};

Object.defindProperty(book,{

year :{

value:2020

},

edition:{
	value:1
},

year:{set:funtion(newValue){
	this.year = newValue
},
	
          get:funtion(){
	return this.year;
}
}
           

});

把数据属性和访问器属性一起定义了

工厂模式,由于JavaScript没有类的定义,那么实现这个工厂模式是定义一个方法

function createPerson(name,age,job){

var obj = new Object();
obj.name = name;
obj.age = age;
obj.job = job;
obj.sayName = function(){
	alert(this.name);
	         };
return obj;
           

};

person1 = create(“lala”,18,“engineer”);

或者这样

function Person(name,age,job){

this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
	alert(this.name);
	         };
           

};//没有newObjct,没有return,使用this

var person2 = new Person(“haha”,20,“engineer”);

按照惯例,构造函数的名字开头是大写的

任何函数,用new来调用,那么它就是构造函数,只要不是用new来调用的,那么它就是普通函数

另一种方式来构造对象

fiction Person(name,age,job){

this.name = name;

this.age = age;

this.job = job;

this.sayName = function(){

alert(this.name);

};

};

var o = new Object();

Person.call(o,“lala”,20,“engineer”);

每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象

原型对象(共享属性和方法):

function Person(){}

Person.prototype.name = “lala”;

Person.prototype.age = 18;

Person.prototype.sayName = function(){

alert(this.name);

};

var person1 = new Person();

var person2 = new Person();

alert(person1.sayName == person2.sayName); //true

无论什么时候,只要创建一个新函数,就会为这个函数创建一个prototype属性,这个属性指向函数的原型对象

每当代码读取某个对象的属性,首先会查看对象实例本身有没有给定名字的属性,如果有就用了,没有就继续搜素指针指向的原型对象

var person = {};

function Person(){}

Person.prototype.name = “lala”;

Person.prototype.age = 18;

Person.prototype.sayName = function (){alert(this.name);};

var person1 = new Person();

person1.name = “haha”;

alert(person1.name); //haha

alert(person1.hasOwnProperty(“name”); //true,因为person1有自己的name属性,如果没有会返回false,通过这个 //方法可以很清楚知道,现在访问的这个属性是实例属性还是原型属性

in 的使用

var person = {};

function Person(){}

Person.prototype.name = “lala”;

Person.prototype.age = 18;

Person.prototype.sayName = function (){alert(this.name);};

var person1 = new Person();

alert(“name” in person1); //true

原型中的toString函数是不可枚举的

使用keys方法获取可枚举属性的字符串数组

var person = {};

function Person(){}

Person.prototype.name = “lala”;

Person.prototype.age = 18;

Person.prototype.sayName = function (){alert(this.name);};

var keys = Object.keys(Person.prototype); //注意这里如果写成Person是不行的

var person1 = new Person();

person1.name = “haha”;

person1.age = 20;

var key1 = Object.keys(person1); //注意这里如果写成person1.prototype是不行的

更常见的封装是

function Person() = {}

Person.prototype = {

name :"lala",
age :18,
sayName: function(){
alert(this.name);
}
           

};

var person = new Person();

alert(person.name); //lala

但是如果这样写

function Person(){}

var person = new Person();

Person.prototype = {

name :“lala”,

age :18

};

alert(person.name); //undefind

留给读者思考prototype指针,上面这种写法的prototype指针发生了变化

通过原生对象的原型,不仅可以用所有默认的方法,还有为它增加新的方法

例子:

String.prototype.startWith = function(text){

return String.indexOf(text) == 0;

};

var mas = “hello world”;

alert(mas.startWith(“h”); //true

我们一般都会使用混合模式来创建对象,既使用构造函数,也使用原型模式

例子:

function Person(name,age,job){

this.name = name;
this.age = age;
this.job = job;
           

}

Person.prototype.sayName = function(){

alert(this.name);
           

};

var person1 = new Person(“lala”,20,“engineer”);

var person2 = new Person(“haha”,20,“engineer”);

person1.sayName();

person2.sayName();

对13点的方法进行部分改造

function Person(name,age,job){

this.name = name;
this.age = age;
this.job = job;

if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
	alert(this.name);
}
}
           

}

var person1 = new Person(“lala”,20,“engineer”);

var person2 = new Person(“haha”,20,“engineer”);

person1.sayName();

person2.sayName();

重温一下call和apply方法

apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.

Function.apply(obj,args)方法能接收两个参数

obj:这个对象将代替Function类里this对象

args:这个是数组,它将作为参数传给Function(args–>arguments)

call:和apply的意思一样,只不过是参数列表不一样.

Function.call(obj,[param1[,param2[,…[,paramN]]]])

obj:这个对象将代替Function类里this对象

params:这个是一个参数列表

分析: Person.apply(this,arguments);

this:在创建对象在这个时候代表的是student

arguments:是一个数组,也就是[“zhangsan”,”21”,”一年级”];

也就是通俗一点讲就是:用student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面

利用apply可以干很多事情:

例如:

求最大值的Math.max(里面只能传n个参数,不能传入数组)

但是这样写可以传入数组

var getMax = Math.max.apply(null,array);