fix img & index.html & .md.html

This commit is contained in:
by931
2022-08-14 03:40:33 +08:00
parent 85b6063789
commit 08120ee33c
3375 changed files with 151526 additions and 1217663 deletions

View File

@@ -1,781 +1,445 @@
<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>13 克隆模式:给你一个分身术.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/白话设计模式 28 讲(完)/00 生活中的设计模式:启程之前,请不要错过我.md.html">00 生活中的设计模式:启程之前,请不要错过我.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/00 生活中的设计模式:启程之前,请不要错过我.md.html">00 生活中的设计模式:启程之前,请不要错过我</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/01 监听模式:坑爹的热水器.md.html">01 监听模式:坑爹的热水器.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/01 监听模式:坑爹的热水器.md.html">01 监听模式:坑爹的热水器</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/02 适配模式:身高不够鞋来凑.md.html">02 适配模式:身高不够鞋来凑.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/02 适配模式:身高不够鞋来凑.md.html">02 适配模式:身高不够鞋来凑</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/03 状态模式:人与水的三态.md.html">03 状态模式:人与水的三态.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/03 状态模式:人与水的三态.md.html">03 状态模式:人与水的三态</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/04 单例模式:你是我生命的唯一.md.html">04 单例模式:你是我生命的唯一.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/04 单例模式:你是我生命的唯一.md.html">04 单例模式:你是我生命的唯一</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/05 职责模式:我的假条去哪了.md.html">05 职责模式:我的假条去哪了.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/05 职责模式:我的假条去哪了.md.html">05 职责模式:我的假条去哪了</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/06 中介模式:找房子问中介.md.html">06 中介模式:找房子问中介.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/06 中介模式:找房子问中介.md.html">06 中介模式:找房子问中介</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/07 代理模式:帮我拿一下快递.md.html">07 代理模式:帮我拿一下快递.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/07 代理模式:帮我拿一下快递.md.html">07 代理模式:帮我拿一下快递</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/08 装饰模式:你想怎么穿就怎么穿.md.html">08 装饰模式:你想怎么穿就怎么穿.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/08 装饰模式:你想怎么穿就怎么穿.md.html">08 装饰模式:你想怎么穿就怎么穿</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/09 工厂模式:你要拿铁还是摩卡.md.html">09 工厂模式:你要拿铁还是摩卡.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/09 工厂模式:你要拿铁还是摩卡.md.html">09 工厂模式:你要拿铁还是摩卡</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/10 迭代模式:下一个就是你了.md.html">10 迭代模式:下一个就是你了.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/10 迭代模式:下一个就是你了.md.html">10 迭代模式:下一个就是你了</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/11 组合模式:自己组装电脑.md.html">11 组合模式:自己组装电脑.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/11 组合模式:自己组装电脑.md.html">11 组合模式:自己组装电脑</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/12 构建模式:想要车还是庄园.md.html">12 构建模式:想要车还是庄园.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/12 构建模式:想要车还是庄园.md.html">12 构建模式:想要车还是庄园</a>
</li>
<li>
<a class="current-tab" href="/专栏/白话设计模式 28 讲(完)/13 克隆模式:给你一个分身术.md.html">13 克隆模式:给你一个分身术.md.html</a>
<a class="current-tab" href="/专栏/白话设计模式 28 讲(完)/13 克隆模式:给你一个分身术.md.html">13 克隆模式:给你一个分身术</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/14 策略模式:怎么来不重要,人到就行.md.html">14 策略模式:怎么来不重要,人到就行.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/14 策略模式:怎么来不重要,人到就行.md.html">14 策略模式:怎么来不重要,人到就行</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/15 命令模式:大闸蟹,走起!.md.html">15 命令模式:大闸蟹,走起!.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/15 命令模式:大闸蟹,走起!.md.html">15 命令模式:大闸蟹,走起!</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/16 备忘模式:好记性不如烂笔头.md.html">16 备忘模式:好记性不如烂笔头.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/16 备忘模式:好记性不如烂笔头.md.html">16 备忘模式:好记性不如烂笔头</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/17 享元模式:颜料很贵必须充分利用.md.html">17 享元模式:颜料很贵必须充分利用.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/17 享元模式:颜料很贵必须充分利用.md.html">17 享元模式:颜料很贵必须充分利用</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/18 外观模式:学妹别慌,学长帮你.md.html">18 外观模式:学妹别慌,学长帮你.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/18 外观模式:学妹别慌,学长帮你.md.html">18 外观模式:学妹别慌,学长帮你</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/19 访问模式:一千个读者一千个哈姆雷特.md.html">19 访问模式:一千个读者一千个哈姆雷特.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/19 访问模式:一千个读者一千个哈姆雷特.md.html">19 访问模式:一千个读者一千个哈姆雷特</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/20 生活中的设计模式:与经典设计模式的不解渊源.md.html">20 生活中的设计模式:与经典设计模式的不解渊源.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/20 生活中的设计模式:与经典设计模式的不解渊源.md.html">20 生活中的设计模式:与经典设计模式的不解渊源</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/21 生活中的设计模式:那些未完待续的设计模式.md.html">21 生活中的设计模式:那些未完待续的设计模式.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/21 生活中的设计模式:那些未完待续的设计模式.md.html">21 生活中的设计模式:那些未完待续的设计模式</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/22 深入解读过滤器模式:制作一杯鲜纯细腻的豆浆.md.html">22 深入解读过滤器模式:制作一杯鲜纯细腻的豆浆.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/22 深入解读过滤器模式:制作一杯鲜纯细腻的豆浆.md.html">22 深入解读过滤器模式:制作一杯鲜纯细腻的豆浆</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/23 深入解读对象池技术:共享让生活更便捷.md.html">23 深入解读对象池技术:共享让生活更便捷.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/23 深入解读对象池技术:共享让生活更便捷.md.html">23 深入解读对象池技术:共享让生活更便捷</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/24 深入解读回调机制:把你技能亮出来.md.html">24 深入解读回调机制:把你技能亮出来.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/24 深入解读回调机制:把你技能亮出来.md.html">24 深入解读回调机制:把你技能亮出来</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/25 谈谈我对设计模式的理解.md.html">25 谈谈我对设计模式的理解.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/25 谈谈我对设计模式的理解.md.html">25 谈谈我对设计模式的理解</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/26 谈谈我对设计原则的思考.md.html">26 谈谈我对设计原则的思考.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/26 谈谈我对设计原则的思考.md.html">26 谈谈我对设计原则的思考</a>
</li>
<li>
<a href="/专栏/白话设计模式 28 讲(完)/27 谈谈我对项目重构的看法.md.html">27 谈谈我对项目重构的看法.md.html</a>
<a href="/专栏/白话设计模式 28 讲(完)/27 谈谈我对项目重构的看法.md.html">27 谈谈我对项目重构的看法</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>13 克隆模式:给你一个分身术</h1>
<p>【故事剧情】</p>
<blockquote>
<p>Tony 最近在看一部电视剧《闪电侠》,里面一个人物叫 Danton Black 的超级人类,拥有复制自身的超能力,能够变身出六个自己,男主角第一次与他交锋时还晕了过去。</p>
<p>Tony 也想要有这种超能力,这样就可以同时处理多件事啦:可以一边敲代码、一边看书、还能一边约妹,哈哈!</p>
<p>当然这是不可能的,虽然现在的克隆技术已经能够克隆羊、克隆狗、克隆猫,但还不能克隆人!就算可以,也不能使克隆出来的自己立刻就变成二十几岁的你,当他长到二十几岁时你已经四十几岁了,他还能理解你的想法吗?</p>
</blockquote>
<p><img src="assets/cdf6fa20-781d-11e8-81a3-e1036ee16107.jpg" alt="img" /></p>
<h3>用程序来模拟生活</h3>
<p>人的克隆是困难的,但程序的克隆是简单的,因为它天生就具有方便复制的特点。在程序设计中,也有一种思想是来源于克隆这一概念,它就是克隆模式。在谈这一模式之前,我们先用程序来模拟一下 Tony 这一 YY 的想法。</p>
<p>源码示例:</p>
<pre><code class="language-python">from copy import copy, deepcopy
class Person:
&quot;&quot;
def __init__(self, name, age):
self.__name = name
self.__age = age
def showMyself(self):
print(&quot;我是&quot; + self.__name + &quot;,年龄&quot; + str(self.__age) + &quot;.&quot;)
def coding(self):
print(&quot;我是码农我在Coding改变世界...&quot;)
def reading(self):
print(&quot;阅读使我快乐!知识使我成长!如饥似渴地阅读是生活的一部分...&quot;)
def fallInLove(self):
print(&quot;春风吹,月亮明,花前月下好相约...&quot;)
def clone(self):
return copy(self)
</code></pre>
<p>测试代码:</p>
<pre><code class="language-python">def testProtoType():
tony = Person(&quot;Tony&quot;, 26)
tony.showMyself()
tony.coding()
tony1 = tony.clone()
tony1.showMyself()
tony1.reading()
tony2 = tony.clone()
tony2.showMyself()
tony2.fallInLove()
</code></pre>
<p>输出结果:</p>
<pre><code>我是Tony,年龄:26
我是码农我在Coding改变世界...
我是Tony,年龄:26
阅读使我快乐!知识使我成长!如饥似渴地阅读是生活的一部分...
我是Tony,年龄:26
春风吹,月亮明,花前月下好相约...
</code></pre>
<p>在上面的例子中Tony 克隆出了两个自己 tony1 和 tony2因为是克隆出来的所有姓名和年龄都一样这样 Tony 就可以同时去敲代码、读书和约会了。</p>
<h4>从剧情中思考克隆模式</h4>
<p>像上面的 Demo 一样,通过拷贝自身的属性来创建一个新对象的过程叫做<strong>克隆模式</strong>。在很多书籍和资料中被称为<strong>原型模式</strong>,但我觉得克隆一词更能切中其主旨。</p>
<p>克隆模式的核心就是一个 Clone 方法Clone 方法的功能就是拷贝父本的所有属性,主要包括两个过程:</p>
<ul>
<li>分配一块新的内存空间给新的对象;</li>
<li>拷贝父本对象的所有属性。</li>
</ul>
<h4>浅拷贝与深拷贝</h4>
<p>要讲清楚这个概念,先来看一个例子,还是基于上面的 Demo我们稍做一些修改。</p>
<pre><code class="language-python">class Person:
&quot;&quot;
def __init__(self, name, age):
self.__name = name
self.__age = age
self.__petList = []
def showMyself(self):
print(&quot;我是&quot; + self.__name + &quot;,年龄&quot; + str(self.__age) + &quot;. 我养了这些宠物:&quot;)
for pet in self.__petList:
print(pet + &quot;\t&quot;, end=&quot;&quot;)
print()
def addPet(self, pet):
self.__petList.append(pet)
def clone(self):
return copy(self)
def deepClone(self):
return deepcopy(self)
</code></pre>
<p>测试代码:</p>
<pre><code class="language-python">def testProtoType2():
tony = Person(&quot;Tony&quot;, 26)
tony.addPet(&quot;小狗Coco&quot;)
print(&quot;父本tony&quot;, end=&quot;&quot;)
tony.showMyself()
tony1 = tony.deepClone()
tony1.addPet(&quot;小猫Amy&quot;)
print(&quot;副本tony1&quot;, end=&quot;&quot;)
tony1.showMyself()
print(&quot;父本tony&quot;, end=&quot;&quot;)
tony.showMyself()
tony2 = tony.clone()
tony2.addPet(&quot;小兔Ricky&quot;)
print(&quot;副本tony2&quot;, end=&quot;&quot;)
tony2.showMyself()
print(&quot;父本tony&quot;, end=&quot;&quot;)
tony.showMyself()
</code></pre>
<p>输出结果:</p>
<pre><code>父本tony我是Tony,年龄26. 我养了这些宠物:
小狗Coco
小狗Coco
副本tony1我是Tony,年龄26. 我养了这些宠物:
小狗Coco 小猫Amy
小狗Coco 小猫Amy
父本tony我是Tony,年龄26. 我养了这些宠物:
小狗Coco
小狗Coco
副本tony2我是Tony,年龄26. 我养了这些宠物:
小狗Coco 小兔Ricky
小狗Coco 小兔Ricky
父本tony我是Tony,年龄26. 我养了这些宠物:
小狗Coco 小兔Ricky
</code></pre>
<p>在上面这个例子中,我们看到“副本 tony1”是通过深拷贝的方式创建的我们对 tony1 对象增加宠物,不会影响 tony 对象。而副本 tony2 是通过浅拷贝的方式创建的,我们对 tony2 对象增加宠物时tony 对象也更着改变。这是因为 Person 类<code>__petList</code>成员是一个可变的引用类型,<strong>浅拷贝只拷贝引用类型对象的指针(指向),而不拷贝引用类型对象指向的值;深拷贝到同时拷贝引用类型对象及其指向的值。</strong></p>
<p>引用类型对象本身可以修改Python 中的引用类型有列表List、字典Dictionary、类对象。Python 在赋值的时候默认是浅拷贝,如</p>
<pre><code>def testList():
list = [1, 2, 3];
list1 = list;
print(&quot;list's id:&quot;, id(list))
print(&quot;list1's id:&quot;, id(list1))
print(&quot;修改之前:&quot;)
print(&quot;list:&quot;, list)
print(&quot;list1:&quot;, list1)
list1.append(4);
print(&quot;修改之后:&quot;)
print(&quot;list:&quot;, list)
print(&quot;list1:&quot;, list1)
</code></pre>
<p>结果:</p>
<pre><code>list's id: 56424568
list1's id: 56424568
修改之前:
list: [1, 2, 3]
list1: [1, 2, 3]
修改之后:
list: [1, 2, 3, 4]
list1: [1, 2, 3, 4]
</code></pre>
<p>通过 Clone 的方式创建对象时,浅拷贝往往是很危险的,因为一个对象的改变另一个对象也同时改变。深拷贝会对一个对象的发生进行完全拷贝,这样两个对象之间就不会相互影响了,你改你的,我改我的。</p>
<p>在使用克隆模式时,除非一些特殊情况(如需求本身就要求两个对象一起改变),<strong>尽量使用深拷贝的方式</strong>(称其为<strong>安全模式</strong>)。</p>
<h3>克隆模式的模型抽象</h3>
<h4>代码框架</h4>
<p>克隆模式非常简单,我们可以对它进行进一步的重构和优化,抽象出克隆模式的框架模型。</p>
<pre><code class="language-python">from copy import copy, deepcopy
class Clone:
&quot;克隆的基类&quot;
def clone(self):
&quot;浅拷贝的方式克隆对象&quot;
return copy(self)
def deepClone(self):
&quot;深拷贝的方式克隆对象&quot;
return deepcopy(self)
</code></pre>
<h4>类图</h4>
<p>上面的代码框架可用类图表示如下:</p>
<p><img src="assets/ebf0ed60-781d-11e8-81a3-e1036ee16107.jpg" alt="enter image description here" /></p>
<h4>基于框架的实现</h4>
<p>有了上面的代码框架之后,我们要实现示例代码的功能就会更简单了。最开始的示例代码我们假设它为 version 1.0,那么再看看基于框架的 version 2.0 吧。</p>
<pre><code class="language-python">class Person(Clone):
&quot;&quot;
def __init__(self, name, age):
self.__name = name
self.__age = age
self.__petList = []
def showMyself(self):
print(&quot;我是&quot; + self.__name + &quot;,年龄&quot; + str(self.__age) + &quot;. 我养了这些宠物:&quot;)
for pet in self.__petList:
print(pet + &quot;\t&quot;, end=&quot;&quot;)
print()
def addPet(self, pet):
self.__petList.append(pet)
def coding(self):
print(&quot;我是码农我在Coding改变世界...&quot;)
def reading(self):
print(&quot;阅读使我快乐!知识使我成长!如饥似渴地阅读是生活的一部分...&quot;)
def fallInLove(self):
print(&quot;春风吹,月亮明,花前月下好相约...&quot;)
</code></pre>
<p>测试代码不用变(同 testProtoType2()),自己跑一下,会发现输出结果和之前的是一样的。</p>
<h4>模型说明</h4>
<p>克隆模式也叫原型模式应用场景非常之广泛。Java 中与基类 Object 融为一体,可以随手就拿来用,只要 implements Cloneabble 接口就默认拥有了克隆的功能。而在 Python 中,克隆模式更是成为了语言本身的部分,因为 Python 中对象的赋值就是一个浅拷贝的过程。</p>
<h5><strong>克隆模式的优点</strong></h5>
<ul>
<li>克隆模式是通过内存拷贝的方式进行复制,比 new 的方式创建对象性能更好;</li>
<li>通过深拷贝的方式,可以方便地创建一个具有相同属性和行为的另一个对象,特别是对于复杂对象,方便性尤为体现。</li>
</ul>
<h5><strong>克隆模式的缺点</strong></h5>
<p>通过克隆的方式创建对象,<strong>不会执行类的构造函数</strong>,这不一定是缺点,但大家使用的时候需要注意这一点。</p>
<h3>应用场景</h3>
<ul>
<li>如果创建新对象(如复杂对象)成本较大,我们可以利用已有的对象进行复制来获得。</li>
<li>当类的初始化需要消耗非常多的资源时,如需要消耗很多的数据、硬件等资源。</li>
</ul>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/白话设计模式 28 讲(完)/12 构建模式:想要车还是庄园.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/白话设计模式 28 讲(完)/14 策略模式:怎么来不重要,人到就行.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997b977d1d3cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>