记录一些前端知识。前端
无序属性的集合,其属性能够包含基本值、对象或者函数,。对象的每一个属性或方 法都有一个名字,而每一个名字都映射到一个值,每一个对象都是基于一个引用类型建立的。数组
基本类型值:Undefined、Null、Boolean、Number、String。app
引用类型值:Obejct函数
建立自定义对象的一个最简单的方式就是建立一个Object的实例,而后给它添加属性和方法。ui
//方式(1)
let a = new Object();
//属性
a.name = "ssssslf";
a.age = 24;
//方法
a.getName = function(){
console.log(this.name)
}
//方式(2)
let a = {
name:"ssssslf",
age:24,
getName:function(){
console.log(this.name)
}
}
复制代码
数据属性和访问器属性this
数据属性:数据属性包含一个数据值的位置。在这个位置能够读取和写入值spa
要修改属性的默认特性,必须使用Object.defineProperty()方法prototype
例子:指针
//参数:属性所在对象,属性名称,描述符对象
Object.defineProperty(a,"name",{
writable:false,//不能修改属性值,只读
value:"slf",
})
console.log(a.name);//slf
a.name = "sslf";
console.log(a.name);//slf
Object.defineProperty(a,"name",{
writable:true,//能修改属性值
value:"slf",
})
console.log(a.name);//slf
a.name = "sslf";
console.log(a.name);//sslf
复制代码
其他方式相似。code
注意:若是修改Configurable,讲其改成false,再将其改成true,会报错。
访问器属性:没有数据值,可是有getter,setter函数
例子:
let a = {
name:"ssssslf",
age:24,
getName:function(){
console.log(this.name)
}
}
Object.defineProperty(a,"_name",{
get:function(){
return this.name;
},
set:function(newValue){
if(newValue === "ssslf"){
this.name = newValue;
}
}
})
a._name = "sslf";
console.log(a);//{name: "ssssslf", age: 24, getName: ƒ}
a._name = "ssslf";
console.log(a);//{name: "ssslf", age: 24, getName: ƒ}
复制代码
以上例子是ECMScript5,旧有方法用: defineGetter , defineSetter.
a.__defineGetter__("_name",function(){
return this.name
})
a.__defineSetter__("_name",function(){
if(newValue === "ssslf"){
this.name = newValue;
}
})
复制代码
Object.defineProperty 设置单个属性,Object.defineProperties设置多个属性
let a = {};
Object.defineProperties(a,{
//数据属性
name:{
value:"slf"
},
age:{
value:"24",
},
//访问器属性
_name:{
get:function(){
return this.name
},
set:function(newValue){
if(newValue === "ssslf"){
this.name = newValue;
}
}
}
})
复制代码
读取属性:Object.getOwnPropertyDescriptor
var descriptor = Object.getOwnPropertyDescriptor(a,"name")
console.log(descriptor.value)//slf
console.log(descriptor.configurable)//false
复制代码
function createPerson(name,age){
//显示建立对象
var o = new Object();
o.name = name;
o.age = age;
o.getName = function(){
return this.name
}
return o;
}
var slf = createPerson("slf",24);
复制代码
//没有显示建立对象,直接将属性方法赋值给this,没有return语句
//构造函数,函数名称大写
function Person(name,age){
//属性
this.name = name;
this.age = age;
//方法
this.getName = function(){
return this.name;
}
}
//建立Person实例,必须使用new操做符
var slf = new Person("slf",24);
复制代码
打印slf
slf是Person的一个实例,slf有一个constructor(构造函数)属性,该属性指向Person 即console.log(slf.constructor == Person) //true
在工厂模式中是没法知道对象类型的,但在这里是能够知道对象类型的。判断对象类型的方式能够用instanceof
console.log(slf instanceof Object) //true 全部的对象都继承Object
console.log(slf instanceof Person)//true
复制代码
(1) 当作构造函数使用 (2) 当作普通函数调用 (3) 在另外一个对象的做用域中调用
//(1)
var person = new Person("slf",24);
person.getName();
//(2)
Person("slf1",25);
window.geName();
//(3)
var other = new Object();
Person.call(other,"slf2",26);
other.getName();
复制代码
var slf1 = new Person("slf1",24);
var slf2 = new Person("slf2",24);
复制代码
上诉代码 slf1,slf2都有getName()方法,可是两个对象的getName()并非同一个Function对象。能够将getName()提取出来到构造函数外部。
function Person(name,age){
this.name = name;
this.age = age;
this.getName = getName;
}
function getName(){
console.log(this.name)
}
//问题:做为全局做用域的函数却只有只被某个对象调用
复制代码
每建立的一个函数都有一个prototype属性,该属性为指针,指向一个对象,该对象有一个constructor属性,即
console.log(Person.prototype.constructor==Person)//true
复制代码
而建立的函数又是Function的实例,也就是
console.log(Person._proto_==Function.prototype)//true
复制代码
_proto_个人理解就是至关于找他们的爸爸
普通类型有_proto_属性,引用类型有_proto_和prototype属性,即
var abc = new Person("slf",24)
console.log(abc.__proto__ == Person.prototype)//true
console.log(abc.prototype) //undefined
复制代码
原型模式和构造函数模式的不一样在于不用在构造函数中定义对象实例的信息,能够直接将这些信息添加到原型对象当中,即prototype中
function Person(){}
//这些属性和方法被全部的实例共享
Person.prototype.name = "slf";
Person.prototype.age = 24;
Person.prototype.getName = function(){
console.log(this.name);
}
var p1 = new Person();
p1.getName();//slf
var p2 = new Person();
console.log(p1.getName == p2.getName)//true
复制代码
查找p1.getName()时候,先查找P1中是否有getName()方法,没有,而后找p1.proto.getName
实例能够访问原型中的值,却没法改变原型当中的值,只能改写原型当中的值,即
function Person(){}
//这些属性和方法被全部的实例共享
Person.prototype.name = "slf";
Person.prototype.age = 24;
Person.prototype.getName = function(){
console.log(this.name);
}
var p1 = new Person();
p1.getName();//slf
var p2 = new Person();
p2.name = "slf1"
p2.getName();//slf1
复制代码
hasOwnProperty() 能够检验一个属性是存在原型中仍是实例中
p1.hasOwnProperty("name") //false
p2.hasOwnProperty("name") //true
复制代码
in 不能够检验一个属性是存在原型中仍是实例中
("name" in p1) //true
("name" in p2) //true
复制代码
判断一个属性存在对象中仍是原型中
function hasPrototypeProperty(object,name){
return !object.hasOwnProperty(name)&&(name in object)
}
hasPrototypeProperty(p1,"name")//true
hasPrototypeProperty(p2,"name")//false //存在实例中
复制代码
function Person(){}
Person.prototype={
name:"slf",
age:24,
getName:function(){
console.log(this.name)
}
}
复制代码
若是要使用constructor
function Person(){}
Person.prototype={
constructor:Person,
name:"slf",
age:24,
getName:function(){
console.log(this.name)
}
}
复制代码
这种方式会形成constructor能够枚举,enumerable=true
var p3 = new Person();
for(let i in p3){console.log(i)}
//constructor name age getName
复制代码
可是原生的constructor不可枚举
Object.defineProperty(Person.prototype,"constructor",{
enumerable:false,
value:Person
})
复制代码
咱们对原型对象所作的任何修改都可以当即在实例中体现,即便先建立实例再修改原型。 可是若是重写Person.prototype就不会了
function Person(){}
Person.prototype={
constructor:Person,
name:"slf",
friends:["s","l"],
age:24,
getName:function(){
console.log(this.name)
}
}
var p1 = new Person();
var p2 = new Person();
p1.friends.push("f");
p1.friends//["s","l","f"]
p2.friends//["s","l","f"]
复制代码
构造模式用于定义属性,原型模式用于定义方法和共享属性,这样每一个实例属性都有本身的一份实例属性副本,但又能够共享方法的引用,节约内存
复制代码
function Person(name,age){
//属性
this.name = name;
this.age = age;
this.friends = ["s","l"],
}
Person.prototype={
constructor:Person,
getName : function(){
return this.name;
}
}
var p1 = new Person("slf1",22);
var p2 = new Person("slf2",23);
p1.friends.push("f");
p1.friends//["s","l","f"]
p2.friends//["s","l"]
p1.getName == p2.getName //true
复制代码
经过判断某个方法是否有效,决定是否要初始化原型
复制代码
function Person(name,age){
//属性
this.name = name;
this.age = age;
this.friends = ["s","l"],
//只有初次调用构造函数才会执行
if(typeof this.getName !='function'){
Person.prototype.getName= function(){
return this.name;
}
}
}
复制代码
建立一个封装建立对象,返回新建立对象的函数
复制代码
function Person(name,age){
var o = new Object();
o.name = name;
o.age = age;
o.getName = function(){
return this.name;
}
return o;
}
var p1 = new Person("slf",24);
复制代码
这个模式的用法,建立一个具备额外方法的特殊数组,但不直接修改Array函数
function SpecialArray(){
var values = new Array();
//添加值
values.push.apply(values,arguments);
//添加方法
values.toPipedString = function(){
return this.join("|");
};
return values
}
var names = new SpecialArray("s","l","f");
names.toPipedString();//s|l|f
复制代码
构造函数返回的对象与构造函数外部建立的对象没有什么不一样,不能用instanceof肯定对象类型
1.建立对象实例不用this.
2.不能使用new操做符调用构造函数
复制代码
function Person(name,age){
var o = new Object();
o.getName = function(){
return name;
}
return o;
}
var p1 = Person("slf",24);
复制代码