农历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)}
。