原型链是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. Java基础--枚举

    1.枚举简介 枚举是由一组固定的常量组成的类型,自定义数据类型. 枚举的常量值一定是可列举的有限值.常量值的类型都是public static final. 下面代码中的Gender 是一种自定义的数 ...

  2. grid布局笔记学习一之父元素(容器)

    HTML代码: <div id="box"> <div class="lbox box1" style="background: # ...

  3. redis 实现发布订阅的功能

    redis 除了作为缓存的功能外还可以用作消息中间件的功能,这片博客主要是介绍一下 redis 整合spring 实现消息的发布和订阅功能: 1:redis依赖,依赖两个包,redis 包, spri ...

  4. Swift5 语言指南(十七) 反初始化

    一个deinitializer一个类的实例被释放之前立即调用.您使用deinit关键字编写deinitializers ,类似于使用init关键字编写初始化程序的方式.Deinitializers仅适 ...

  5. Linux下Clamav 杀毒软件安装使用文档

    一.安装Clamav杀毒工具 0.安装Clamav需要的依赖包 yum install libxml* openssl* -y 1.创建clamav组 groupadd clamav 2.创建clam ...

  6. Jupyter中python3之numpy练习

    ---恢复内容开始--- Numpy_pratice In [2]: n = 10 L = [i for i in range(n)] In [3]: L * 2 Out[3]: [0, 1, 2, ...

  7. (转)linux中nmcli命令的使用及网络配置

    原文:https://blog.51cto.com/groot/1847482 http://www.178linux.com/44076----CentOS7中nmcli网络管理及使用详解 http ...

  8. WebView使用_WebView监听网页下载_DownloadManager使用

    最近在做一个较简单的项目:通过一个webview来显示一个网页的App 这个网页有下载的功能,关于这一功能需要用到两个知识点: 1.webview监听网页的下载链接.(webview默认情况下是没有开 ...

  9. jquery根据name属性查找元素

    $("div[id]") //选择所有含有id属性的div元素 $("input[name='newsletter']") //选择所有的name属性等于'ne ...

  10. Mybatis之基于XML的调用存储过程与手动回滚事务

    一.调用存储过程 一.返回单个值 1.存储过程准备 这里先创建一个存储过程,传入参数为age,传出参数为count.然后先测试一下是否正确. CREATE DEFINER=`root`@`localh ...