JS基础——JavaScript原型和原型链及实际应用
构造函数
function Stu(name,age){ this.name=name; this.age=age; }
instanceof 查看引用类型对象是属于哪个构造函数的方法,通过__proto__ 一直往上找prototype,直到找到Object
原型规则和示例
所有的引用类型(数组/对象/函数)都可有扩展属性,都有一个隐式原型__proto__属性,所有函数都可以扩展prototype显示原型属性,属性值是个普通的对象,
所有的引用类型试图得到一个它本身的某个属性,会通过它的隐式原型__proto__去找它构造函数中的prototype
// 不希望打印出原型的属性,只打印自身属性 for(let item of f){ if(f.hasOwnProperty(item)){ console.log(item) } }
原型链
let f =new Foo(); f.alertName= function(){ // 方法具体实现 } f.toString() //toString方法在Foo原型中找,找不到接着要去 f.__proto__.__proto__中查找
New一个对象的过程
- 创建一个新的对象
- this指向这个新的对象
- 执行代码,即对this赋值
- 返回this
原型链继承
function Elem(id){ this.elem =document.getElementById(id); } Elem.prototype.html =function(val){ if(val){ return this.elem.innerHTML; } this.elem.innerHTML= val; return this; //将Elem对象返回 } Elem.prototype.on =function(type,func){ this.elem.addEventListener(type,func); return this; } const elem =new Elem('div1'); elem.html('张三').on('click',function(){ console.log('点击了文本,打印张三'); }).html(‘李四’)
实际应用
新建js文件my-z.js,如下是my-z.js文件源码,解释: slice.call能将具有length属性的对象转成数组 document.querySelectorAll(selector) 是个类数组, 没有.slice 原型,所以需要call,
… 或者[].slice.call(arguments, 0)
(function(window){ var Z = function(dom,selector) { var i,len =dom? dom.length: 0; for(i=0;i<dom.length;i++){ this[i] =dom[i]; } this.length =len; this.selector =selector || '' } var zepto = {} zepto.Z= function(dom,selector){ return new Z(dom,selector) } zepto.init =function(selector){ var slice = Array.prototype.slice; var dom =slice.call(document.querySelectorAll(selector)) //slice.call能将具有length属性的对象转成数组 document.querySelectorAll(selector) 是个类数组, 没有.slice 原型,所以需要call return zepto.Z(dom,selector); } var $=function(selector){ return zepto.init(selector) } $.fn = { css : function(key,value) { alert(key+':'+value); return this; }, html : function() { return this[0].innerHTML; } } Z.prototype = $.fn; window.$=$; })(window);
在index.html 引用该文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>prototype</title> <body> <div id="div1">div</div> <p>title1</p> <p>title2</p> <p>title3</p> <p>title4</p> <!--<script type="application/javascript" src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>--> <script type="application/javascript" src="my-z.js"></script> </head> <script type="application/javascript"> $('#div1').css('font-size','25px').css('color','#1ecc24') //链式调用 alert($('#div1').html()) </script> </body> </html>
JS插件扩展
为什么要把原型方法放在$.fn?
- 只有$会暴露在window 全局变量,暴露多个变量容易造成变量的污染
- 将插件扩展到$.fn.xxx这个web api 中,方便使用
示例如下所示:
$.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; i = 2; } if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { if ( (options = arguments[ i ]) != null ) { for ( name in options ) { src = target[ name ]; copy = options[ name ]; if ( target === copy ) { continue; } // 当用户想要深度操作时,递归合并 // copy是纯对象或者是数组 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { // 如果是数组 if ( copyIsArray ) { // 将copyIsArray重新设置为false,为下次遍历做准备。 copyIsArray = false; // 判断被扩展的对象中src是不是数组 clone = src && jQuery.isArray(src) ? src : []; } else { // 判断被扩展的对象中src是不是纯对象 clone = src && jQuery.isPlainObject(src) ? src : {}; } // 递归调用extend方法,继续进行深度遍历 target[ name ] = jQuery.extend( deep, clone, copy ); // 如果不需要深度复制,则直接把copy(第i个被扩展对象中被遍历的那个键的值) } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // 原对象被改变,因此如果不想改变原对象,target可传入{} return target; }; $.fn.highlight = function (options) { // 合并默认值和用户设定值: var opts = $.fn.extend({}, $.fn.highlight.defaults, options); this.css('backgroundColor', opts.backgroundColor).css('color', opts.color); return this; } // 设定默认值: $.fn.highlight.defaults = { color: '#d8d030', backgroundColor: '#ecfdde' }
验证插件效果:
<script type="application/javascript"> //验证插件扩展 $('#div1').highlight({ color: '#fff', backgroundColor: '#333' }) </script>