📌 原型
任何对象都有一个原型对象,这个原型对象由内部属性**proto指向它的构造函数的prototype**指向的对象 任何对象都是由一个构造函数创建的,被创建的对象都可以获得构造函数的**prototype**属性 任何对象都有一个**constructor属性,指向创建此对象的构造函数**
注意 :对象是没有prototype属性的,只有方法才有prototype属性**
// 直接调用Person()就是一个普通函数
function Person() {}
// 只有通过new产生实例对象,这个函数才是new出来实例对象的构造函数
var p = new Person();
// 只有方法才有prototype属性,普通对象无prototype
console.log(Person.prototype); // Object{}
console.log(p.prototype); // undifined
//任何对象都是有构造函数constructor,由构造函数创建的对象也可以获得构造函数的引用
//此处只是打印下列对象的构造函数是什么。
// 实例对象的constructor属性指向创建该实例对象的构造函数
console.log(p.constructor); //function Person(){}
console.log(Person.constructor); //function Function(){}
console.log({}.constructor); // function Object(){}
console.log(Object.constructor); // function Function() {}
console.log([].constructor); //function Array(){}
// 只要是对象就是有构造函数来创建的
// 其内部的__proto__是从构造函数的prototype衍生的一个指向
// 而构造函数的prototype也是一个对象,那么它肯定也由一个构造函数创建
// 它是一个Object {} 对象,它的构造函数肯定是Object,所以就会有一个指针_proto_指向Object.prototype
// 最后Object.prototype因为没有_proto_,指向null,这样就构成了一个原型链
通过 **new关键字** 创建的实例对象:
实例对象的proto和**其构造函数的prototype相等 实例对象的__proto属性指向了方法的prototype属性,且constructor指向了方法prototype的**constructor属性
📌 原型链
function Person(name){
this.name = name;
}
var p = new Person();
//p ---> Person.prototype --->Object.prototype---->null
// p的构造函数是Person创建的,那么Person.prototype就是继承的第一个原型
p.__proto__ === Person.prototype
// Person.prototype也是一个Object对象,即是Object构造函数创建的,那么就是继承了Object.prototype
Person.prototype.__proto__ === Object.prototype
// Object.prototype再往上就没有__proto__指向了,等于null
Object.prototype.__proto__ === null
原型链核心: 依赖于实例对象的proto指向,当自身不存在属性时,就一层层向上扒该实例对象的构造函数,直至顶级Object构造函数的prototype就没有proto指向了
**
属性搜索原则原则:
- 当访问一个对象的成员的时候,会现在自身找有没有,如果找到直接使用
- 如果没有找到,则去原型链指向的对象的构造函数的prototype中找,找到直接使用,没找到就返回undifined或报错
📌 闭包立即执行函数
function test() {
var a = 1;
function plus(){
a++
console.log(a)
}
return plus
}
var plus = test()
plus(); // 2
plus(); // 3
plus(); // 4
-----------------------------------------
function test() {
var a = 1;
function plus(){
a++
console.log(a)
}
window.plus = plus
}
window.plus(); // 2
window.plus(); // 3
window.plus(); // 4
立即执行函数配合闭包 实现模块化中应用
(function(){
var meg = "hello zdx";
function say(arg){
arg = arg || meg;
console.log(arg)
}
window.say = say;
})(window)
window.say(); //"hello zdx"
函数中使用** window 与 return 的区别?**
- 相同点:
都是将其内部的值暴露给全局,以便全局进行调用
- 不同点:
- return 需要一个全局变量接收函数执行后的返回值,在全局使用全局变量
- window 在函数内部直接将值保存到window的自定义属性上,全局使用即可
📌 插件的开发
立即执行函数,可以防止全局变量污染及函数作用域的污染 一般在立即函数内的构造函数中定义插件需要使用的参数 一般在立即函数内构造函数原型prototype上定义插件的方法 通过window将立即执行函数中的构造函数挂载到全局 全局中即可通过new关键字创建该构造函数的实例对象,从而可调用到该构造函数上的方法
;(function () {
function Test(){
}
Test.prototype = {
}
window.Test = Test;
})();
var test = new Test()
关于立即执行函数前 ;分号的原因:
;(function (){
function Computed(opt){
this.firstNum = opt.firstNum;
this.secendNum = opt.secendNum;
};
Computed.prototype = {
plus: function () {
return this.firstNum + this.secendNum
},
minus: function () {
return this.firstNum - this.secendNum
},
mul: function () {
return this.firstNum * this.secendNum
},
div: function () {
return this.firstNum / this.secendNum
}
}
window.Computed = Computed
})()
var computed = new Computed({
firstNum: 10,
secendNum: 5
})
var plusRes = computed.plus()
var minusRes = computed.minus()
var mulRes = computed.mul()
var divRes = computed.div()
console.log(plusRes, minusRes, mulRes, divRes)