原型链是js面向对象的基础,非常重要。
一,创建对象的几种方法:
1,字面量
var o1 = {
name:'o1'
};
2,构造函数
var M = function(name){
this.name = name;
};
var o2 = new M('o2');
var a = {} 其实是 var a = new Object()的语法糖,推荐使用前者
var a = [] 其实是 var a = new Array()的语法糖,推荐使用前者
function Foo(){} 其实是 var Foo = new Function()的语法糖,推荐使用前者
 

3,Object.create(Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。 )
var P = {name:'o3'};
var o3 = Object.create(P);

二,原型链

JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……
那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null。
 Object.getPrototypeOf(Object.prototype) //null

Object.prototype === Object.getPrototypeOf( {} ); //true
5条原型规则
1,所有的引用类型(数组,对象,函数),都具有对象特性,即可自由扩展属性
2,所有的引用类型(数组,对象,函数),都有一个__proto__属性(隐式原型),属性值是一个普通的对象
3,所有的函数,都有一个prototype属性(显式原型),属性值也是一个普通的对象
4,所有的引用类型(数组,对象,函数)__proto__属性值指向它的构造函数的prototype属性值
5,当试图得到一个引用类型(数组,对象,函数)的某个属性时,如果这个引用类型本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找

看下图

 

三,instanceof原理

判断一个函数是否是一个变量的构造函数

工作原理:判断实例对象的__proto__属性和构造函数的prototype是否同一个地址,只要在原型链上的构造函数,都会被instanceof认为是实例的构造函数。如图:

    // 判断实例对象的proto属性和构造函数的prototype是否同一个地址
// 只要在原型链上的构造函数,都会被instanceof认为是实例的构造函数
var M = function(name) { this.name = name; };
var o2 = new M('o2');
o2.__proto__ === M.prototype //true
M.prototype.__proto__ === Object.prototype //true
o2.__proto__.__proto__ === Object.prototype //true o2 instanceof M //true
o2 instanceof Object //true // 用constructor属性判断更严谨
o2.__proto__.constructor === M //true
o2.__proto__.constructor === Object //false

四,new运算符工作原理

    // new运算符及背后工作原理 new后跟构造函数
// 1,一个新对象被创建,它继承自func.prototype(构造函数的原型对象)
// 2,构造函数func被执行,执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例
// 3,如果构造函数返回了一个“对象”,那么这个对象会取代整个new出来的结果,如果构造函数没有返回对象,那么new出来的结果为步骤1创建的对象
var new2 = function(func) {
var o = Object.create(func.prototype);
var k = func.call(o);
if (typeof k === 'object' && k != null) {
return k;
} else {
return o;
}
};

五,原型链继承的例子

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>proto</title>
</head> <body>
<div id="div1">123</div>
<script>
// 封装DOM查询
function Elem(id) {
this.elem = document.getElementById(id);
} Elem.prototype.html = function(val) {
var elem = this.elem;
if (val) {
elem.innerHTML = val;
return this;//方便链式操作
} else {
return elem.innerHTML;
}
} Elem.prototype.on = function(type, fn) {
var elem = this.elem;
elem.addEventListener(type, fn);
return this;//方便链式操作
} var div1 = new Elem('div1');
console.log(div1.html());
div1.html('<p>234p</p>').on('click', function() {
alert('1');
}).html('<p>js</p>');
</script>
</body> </html>

六:原型实际应用

1,看一个平时使用jquery或者zepto的例子:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>jquery</title>
</head> <body>
<p>jquery 1</p>
<p>jquery 2</p>
<p>jquery 3</p>
<div id="div1">
<p>jquery test in div</p>
</div>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
var $p = $('p');
$p.css('color', 'red'); //css是原型方法
console.log($p.html()); //html是原型方法,这里只打印第一个 jquery 1 var $div = $('#div1');
$div.find('p').css('color', 'blue'); //find,css是原型方法
console.log($div.html()); //html是原型方法 <p style="color: blue;">jquery test in div</p>
</script>
</body> </html>
2,zepto如何使用原型(简化版)-my-zepto.js
(function(window) {
// 空对象
var zepto = {}; // 构造函数
function Z(dom, selector) {
var i, len = dom ? dom.length : 0;
for (i = 0; i < len; i++) {
this[i] = dom[i];
}
this.length = len;
this.selector = selector || '';
} zepto.Z = function(dom, selector) {
// 注意,出现了 new 关键字
return new Z(dom, selector);
} zepto.init = function(selector) {
// 源码中,这里的处理情况比较复杂,但因为本次只针对原型,因此这里就弱化了
var slice = Array.prototype.slice;
var dom = slice.call(document.querySelectorAll(selector));
return zepto.Z(dom, selector);
} // 使用zepto的$
var $ = function(selector) {
return zepto.init(selector);
}
window.$ = $; $.fn = {
constructor: zepto.Z,
css: function(key, value) {
console.log('css'); },
html: function(value) {
// console.log('html');
return '这是一个模拟的html函数';
}
} zepto.Z.prototype = Z.prototype = $.fn; //!!! })(window)
测试:新建zepto.html
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>zepto</title>
</head> <body>
<p>zepto 1</p>
<p>zepto 2</p>
<p>zepto 3</p>
<div id="div1">
<p>zepto test in div</p>
</div>
<script src="./my-zepto.js"></script>
<script>
var $p = $('p');
$p.css('color', 'red'); //css是原型方法
console.log($p.html()); //html是原型方法,这是一个模拟的html函数"
</script>
</body> </html>
3,jquery如何使用原型(简化版)-my-jquery.js
(function(window) {
var jQuery = function(selector) {
// 注意new关键字,第一步就找到了构造函数
return new jQuery.fn.init(selector);
}
window.$ = jQuery; // 初始化 jQuery.fn
jQuery.fn = jQuery.prototype = { //!!!
constructor: jQuery, // 其他函数
css: function(key, value) { },
html: function(value) {
return 'html'; }
} // 定义构造函数-简化版
var init = jQuery.fn.init = function(selector) {
var slice = Array.prototype.slice;
var dom = slice.call(document.querySelectorAll(selector)); var i, len = dom ? dom.length : 0;
for (i = 0; i < len; i++) {
this[i] = dom[i];
}
this.length = len;
this.selector = selector || '';
} // 定义原型
init.prototype = jQuery.fn; })(window)

测试:新建jquery.html

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>jquery</title>
</head> <body>
<p>jquery 1</p>
<p>jquery 2</p>
<p>jquery 3</p>
<div id="div1">
<p>jquery test in div</p>
</div>
<script src="./my-jquery.js"></script>
<script>
var $p = $('p');
$p.css('color', 'red'); //css是原型方法
console.log($p.html()); //html是原型方法,这里只打印第一个 "jquery 1"
</script>
</body> </html>
4,如何体现原型的扩展性-插件机制
思考:为何要把原型方法放在$.fn?:扩展插件。(第一,构造函数的 prototype 肯定得指向能扩展的对象;第二,$.fn 肯定得指向能扩展的对象)
看一个简单的插件的例子:
$.fn.getNodeName = function(){
return this[0].nodeName;
}

好处:

1,只有$会暴露在window全局变量
2,将插件扩展统一到 $.fn.xxx 这一个接口,方便使用

实践:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>jquery</title>
</head> <body>
<p>jquery 1</p>
<p>jquery 2</p>
<p>jquery 3</p>
<div id="div1">
<p>jquery test in div</p>
</div>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
// 插件扩展
$.fn.getNodeName = function(){
// console.log(this);
console.log(this[0].nodeName);
}
</script>
<script>
// 验证
var $p = $('p');
$p.getNodeName() //P
$div1 = $('#div1');
$div1.getNodeName() //DIV
</script>
</body> </html>

JavaScript原型与原型链,原型的实际应用的更多相关文章

  1. javascript中的对象,原型,原型链和面向对象

    一.javascript中的属性.方法 1.首先,关于javascript中的函数/“方法”,说明两点: 1)如果访问的对象属性是一个函数,有些开发者容易认为该函数属于这个对象,因此把“属性访问”叫做 ...

  2. JavaScript中的继承(原型链)

    一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...

  3. 【javascript基础】4、原型与原型链

    前言 荒废了好几天,在宿舍闷了几天了,一直想着回家放松,什么也没搞,论文就让老师催吧.不过,闲的没事干的感觉真是不好,还是看看书,写写博客吧,今天和大家说说函数的原型. 原型是什么 第一次看到这个的时 ...

  4. JavaScript 变量、函数与原型链

    定义 || 赋值 1-函数的定义 函数定义的两种方式: “定义式”函数:function fn(){ alert("哟,哟!"); } “赋值式”函数:var fn = funct ...

  5. JavaScript系列:再巩固-原型链

    图 1.实例:'对象(实例)'有属性__proto__,指向该对象(实例)的'构造函数的原型对象'. 2.方法:'构造函数'除了有属性__proto__,所有构造函数方法的__proto__指向Fun ...

  6. 深入理解JavaScript中的继承:原型链篇

    一.何为原型链 原型是一个对象,当我调用一个对象的方法时,如果该方法没有在对象里面,就会从对象的原型去寻找.JavaScript就是通过层层的原型,形成原型链. 二.谁拥有原型 任何对象都可以有原型, ...

  7. JavaScript中的继承与原型链

    先看一个例子 function User(){} var u1 = new User(); console.log(u1.prototype);// undefined 使用对象实例无法访问到prot ...

  8. javascript中的构造函数和原型及原型链

    纯属个人理解,有错误的地方希望大牛指出,以免误人子弟 1.构造函数: 构造函数的作用 : 初始化由new创建出来的对象    new 的作用: 创建对象(空对象) new 后面跟的是函数调用,使用ne ...

  9. Javascript之其实我觉得原型链没有难的那么夸张!

    原型链.闭包.事件循环等,可以说是js中比较复杂的知识了,复杂的不是因为它的概念,而是因为它们本身都涉及到很多的知识体系.所以很难串联起来,有一个完整的思路.我最近想把js中有点意思的知识都总结整理一 ...

  10. 还在问什么是JavaScript构造函数、实例、原型对象以及原型链?看完这篇你就懂

    1概述 ES6, 全称 ECMAScript 6.0 ,2015.06 发版.在ES6之前,对象不是基于类创建的,而是用一种称为构造函数的特殊函数来定义对象和它们的特征. 2构造函数 构造函数是一种特 ...

随机推荐

  1. js内存空间的那点事

    由于js具有自动垃圾回收机制,导致接触js后一直没去关注js的内存分配及变量回收等原理,只是懵懂的了解用变量标记法(null)可以手动的去清除或是回收:是时候弥补这个大坑了... 垃圾回收两种方法 一 ...

  2. Elasticsearch 自定义多个分析器

    分析器(Analyzer) Elasticsearch 无论是内置分析器还是自定义分析器,都由三部分组成:字符过滤器(Character Filters).分词器(Tokenizer).词元过滤器(T ...

  3. 微信小程序:scroll滑到指定位置

    概述 这是我开发微信小程序遇到的坑中的一个,专门记录下来,供以后开发时参考,相信对其他人也有用. scroll滑到指定位置,有两种解决方案,一种是用scroll-view标签,另一种是用wx.page ...

  4. Java匹马行天下之JavaSE核心技术——Java基础语法

    Java基础语法 一.   认识Java 1. Java 简介 java 是一种高级的面向对象的程序设计语言,使用Java语言编写的程序时跨平台的.从pc到手机,都有Java开发的程序和游戏,Java ...

  5. MySQL的时间、日期型

    MySQL的时间.日期型 MySQL中表示时间值的有DATE.时间类型为DATETIME.DATE.TIMESTAMP.TIME和YEAR.每个时间类型有一个有效值范围和一个"零" ...

  6. 聊聊我面试过的一个最奇葩的 Java 程序猿!

    上周我聊了聊最让我反感的 10 种程序猿,无奈一个小时就进行了删除,详细原因就不说了,容易招黑. 今天聊的我面试过的最奇葩的一个程序猿,绝对是奇葩中的奇葩,简直是程序猿中的另类,最让我反感的程序猿又添 ...

  7. 【Collection、泛型】

    [Collection.泛型] 主要内容 Collection集合 迭代器 增强for 泛型 第一章 Collection集合 1.1 集合概述 集合:集合是java中提供的一种容器,可以用来存储多个 ...

  8. [视频]K8飞刀 WordPress XSS添加管理员 & GetShell 教程

    [视频]K8飞刀 WordPress  XSS添加管理员 & GetShell 教程 https://pan.baidu.com/s/1hq4LsmK

  9. 一些java多线程的经验

    多线程的时候,可以try--catch后再catch中加continue让程序继续运行(当然,前提是这个异常的数据不影响后续的操作)

  10. OS开发(2):自定义tabbar | 导航条 | 突显中间按钮

    tabbar是放在APP底部的控件,也叫navigationbar或导航条.常见的APP都使用tabbar来进行功能分类的管理,比如微信.QQ等等. 需求是这样的,需要一个特殊一点的tabbar,要求 ...