記錄一些前端知識。前端
無序屬性的集合,其屬性能夠包含基本值、對象或者函數,。對象的每一個屬性或方 法都有一個名字,而每一個名字都映射到一個值,每一個對象都是基於一個引用類型建立的。數組
基本類型值: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);
複製代碼