📌 原型
任何对象都有一个原型对象,这个原型对象由内部属性**proto指向它的构造函数的prototype**指向的对象 任何对象都是由一个构造函数创建的,被创建的对象都可以获得构造函数的**prototype**属性 任何对象都有一个**constructor属性,指向创建此对象的构造函数**
注意 :对象是没有prototype属性的,只有方法才有prototype属性**
// 直接调用Person()就是一个普通函数function Person() {}// 只有通过new产生实例对象,这个函数才是new出来实例对象的构造函数var p = new Person();// 只有方法才有prototype属性,普通对象无prototypeconsole.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.prototypePerson.prototype.__proto__ === Object.prototype// Object.prototype再往上就没有__proto__指向了,等于nullObject.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(); // 2plus(); // 3plus(); // 4-----------------------------------------function test() {var a = 1;function plus(){a++console.log(a)}window.plus = plus}window.plus(); // 2window.plus(); // 3window.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)
