農曆2019即將過去,趁着年前幾天上班事情少,整理了一下javascript的基礎知識,在此給你們作下分享,喜歡的大佬們能夠給個小贊。本文在github也作了收錄。javascript
本人github: github.com/Michael-lzg前端
每一個構造函數(constructor)都有一個原型對象(prototype), 原型對象都包含一個指向構造函數的指針, 而實例(instance)都包含一個指向原型對象的內部指針.vue
咱們先來看一個例子java
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function() {
alert(this.name)
}
}
var person1 = new Person('Zaxlct', 28, 'Engineer')
var person2 = new Person('Mick', 23, 'Doctor')
複製代碼
上面的例子中 person1 和 person2 都是 Person 的實例。這兩個實例都有一個 constructor (構造函數)屬性,該屬性(是一個指針)指向 Person。 即:webpack
console.log(person1.constructor == Person) //true
console.log(person2.constructor == Person) //true
複製代碼
每一個構造函數都有一個 prototype 屬性,指向調用該構造函數而建立的實例的原型,也就是這個例子中的 person1 和 person2 的原型。git
function Person() {}
Person.prototype.name = 'Zaxlct'
Person.prototype.age = 28
Person.prototype.job = 'Engineer'
Person.prototype.sayName = function() {
alert(this.name)
}
var person1 = new Person()
person1.sayName() // 'Zaxlct'
var person2 = new Person()
person2.sayName() // 'Zaxlct'
console.log(person1.sayName == person2.sayName) //true
複製代碼
這是每個 JavaScript 對象(除了 null )都具備的一個屬性,叫proto,這個屬性會指向該對象的原型。es6
function Person() {}
var person1 = new Person()
console.log(person1.__proto__ === Person.prototype) // true
複製代碼
每一個原型都有一個 constructor 屬性指向關聯的構造函數github
function Person() {}
var person1 = new Person()
console.log(Person === Person.prototype.constructor) // true
console.log(person1.__proto__ === Person.prototype) // true
複製代碼
當讀取實例的屬性時,若是找不到,就會查找與對象關聯的原型中的屬性,若是還查不到,就去找原型的原型,一直找到最頂層爲止。web
function Person() {}
Person.prototype.name = 'Kevin'
var person = new Person()
person.name = 'Daisy'
console.log(person.name) // Daisy
delete person.name
console.log(person.name) // Kevin
複製代碼
在這個例子中,咱們給實例對象 person 添加了 name 屬性,當咱們打印 person.name 的時候,結果天然爲 Daisy。面試
可是當咱們刪除了 person 的 name 屬性時,讀取 person.name,從 person 對象中找不到 name 屬性就會從 person 的原型也就是 person.proto ,也就是 Person.prototype 中查找,幸運的是咱們找到了 name 屬性,結果爲 Kevin。
語法:Object.create(proto, [propertiesObject])
方法建立一個新對象,使用現有的對象來提供新建立的對象的 proto。
// new Object() 方式建立
var a = { rep: 'apple' }
var b = new Object(a)
console.log(b) // {rep: "apple"}
console.log(b.__proto__) // {}
console.log(b.rep) // {rep: "apple"}
// Object.create() 方式建立
var a = { rep: 'apple' }
var b = Object.create(a)
console.log(b) // {}
console.log(b.__proto__) // {rep: "apple"}
console.log(b.rep) // {rep: "apple"}
複製代碼
經典面試題
var obj1 = { name: 'one' }
obj2 = Object.create(obj1)
obj2.name = 'two'
console.log(obj1.name)
//one
var obj1 = { prop: { name: 'one' } }
obj2 = Object.create(obj1)
obj2.prop.name = 'two'
console.log(obj1.prop.name)
//two
var obj1 = { list: ['one', 'one', 'one'] }
obj2 = Object.create(obj1)
obj2.list[0] = 'two'
console.log(obj1.list[0])
//two
複製代碼
在函數內部定義的變量和函數若是不對外提供接口,那麼外部將沒法訪問到,也就是變爲私有變量和私有函數。
function Obj() {
var a = 0 //私有變量
var fn = function() {
//私有函數
}
}
var o = new Obj()
console.log(o.a) //undefined
console.log(o.fn) //undefined
複製代碼
當定義一個函數後經過 「.」爲其添加的屬性和函數,經過對象自己仍然能夠訪問獲得,可是其實例卻訪問不到,這樣的變量和函數分別被稱爲靜態變量和靜態函數。
function Obj() {}
Obj.a = 0 //靜態變量
Obj.fn = function() {
//靜態函數
}
console.log(Obj.a) //0
console.log(typeof Obj.fn) //function
var o = new Obj()
console.log(o.a) //undefined
console.log(typeof o.fn) //undefined
複製代碼
在面向對象編程中除了一些庫函數咱們仍是但願在對象定義的時候同時定義一些屬性和方法,實例化後能夠訪問,JavaScript也能作到這樣。
function Obj(){
this.a=[]; //實例變量
this.fn=function(){ //實例方法
}
}
console.log(typeof Obj.a); //undefined
console.log(typeof Obj.fn); //undefined
var o=new Obj();
console.log(typeof o.a); //object
console.log(typeof o.fn); //function
複製代碼
題目以下
function Foo() {
getName = function() {
alert(1)
}
return this
}
Foo.getName = function() {
alert(2)
}
Foo.prototype.getName = function() {
alert(3)
}
var getName = function() {
alert(4)
}
function getName() {
alert(5)
}
//請寫出如下輸出結果:
Foo.getName()
getName()
Foo().getName()
getName()
new Foo.getName()
new Foo().getName()
new new Foo().getName()
複製代碼
解讀:首先定義了一個叫 Foo 的函數,以後爲 Foo 建立了一個叫 getName 的靜態屬性存儲了一個匿名函數,以後爲 Foo 的原型對象新建立了一個叫 getName 的匿名函數。以後又經過函數變量表達式建立了一個 getName 的函數,最後再聲明一個叫 getName 函數。
先來劇透一下答案,再來看看具體分析
//答案:
Foo.getName() //2
getName() //4
Foo().getName() //1
getName() //1
new Foo.getName() //2
new Foo().getName() //3
new new Foo().getName() //3
複製代碼
function Foo() {
getName = function() {
alert(1)
}
return this
}
var getName //只提高變量聲明
function getName() {
alert(5)
} //提高函數聲明,覆蓋var的聲明
Foo.getName = function() {
alert(2)
}
Foo.prototype.getName = function() {
alert(3)
}
getName = function() {
alert(4)
} //最終的賦值再次覆蓋function getName聲明
getName() //最終輸出4
複製代碼
function(){alert(1)}
。