- 浏览: 45771 次
- 性别:
- 来自: 湖南
最新评论
-
laj12347:
javascript 闭包真是牛逼呀。。看了好久,终于有点 ...
JavaScript: The Good Parts 读书笔记(二) -
mu0001:
赞一个,很不错。以现在的知识来看,先看了第一部分。
JavaScript 数据访问(翻译自High Performance Javascript 第二章) -
e421083458:
得买本书好好看看了!
JavaScript 数据访问(翻译自High Performance Javascript 第二章) -
adamed:
这本书已经有中文版出版了。。到处都可以买到。高性能 javas ...
JavaScript 数据访问(翻译自High Performance Javascript 第二章) -
jiyanliang:
elvishehai 写道来源于那里的呀,写的很不错,学习了. ...
JavaScript 数据访问(翻译自High Performance Javascript 第二章)
4.Function Pattern
- Namespace Pattern
Namespaces help reduce the number of globals required by our programs and at the same time also help avoid naming collisions or excessive name prefixing. JavaScript doesn’t have namespaces built into the language syntax, but this is a feature that is quite easy to achieve. Instead of polluting the global scope with a lot of functions, objects, and other variables, you can create one (and ideally only one) global object for your application or library. Then you can add all the functionality to that object. Consider the following example:// BEFORE: 5 globals // Warning: antipattern // constructors function Parent() {} function Child() {} // a variable var some_var = 1; // some objects var module1 = {}; module1.data = {a: 1, b: 2}; var module2 = {};
You can refactor this type of code by creating a single global object for your application, called, for example, MYAPP, and change all your functions and variables to become properties of your global object:// AFTER: 1 global // global object var MYAPP = {}; // constructors MYAPP.Parent = function () {}; MYAPP.Child = function () {}; // a variable MYAPP.some_var = 1; // an object container MYAPP.modules = {}; // nested objects MYAPP.modules.module1 = {}; MYAPP.modules.module1.data = {a: 1, b: 2}; MYAPP.modules.module2 = {};
For the name of the global namespace object, you can pick, for example, the name of your application or library, your domain name, or your company name. Often developers use the convention of making the global variable ALL CAPS, so it stands out to the readers of the code. (But keep in mind that all caps are also often used for constants.)
This pattern is a good way to namespace your code and to avoid naming collisions in your own code, and collisions between your code and third-party code on the same page, such as JavaScript libraries or widgets. This pattern is highly recommended and perfectly applicable for many tasks, but it does have some drawbacks:
• A bit more to type; prefixing every variable and function does add up in the total
amount of code that needs to be downloaded
• Only one global instance means that any part of the code can modify the global
instance and the rest of the functionality gets the updated state
• Long nested names mean longer (slower) property resolution lookups
The sandbox pattern discussed later in the chapter addresses these drawbacks.
- Declaring Dependencies
JavaScript libraries are often modular and namespaced, which enables you to include only the modules you require. For example, in YUI2 there’s a global variable YAHOO, which serves as a namespace, and then modules that are properties of the global variable, such as YAHOO.util.Dom (the DOM module) and YAHOO.util.Event (Events module).
It’s a good idea to declare the modules your code relies on at the top of your function or module. The declaration involves creating only a local variable and pointing to the desired module:var myFunction = function () { // dependencies var event = YAHOO.util.Event, dom = YAHOO.util.Dom; // use event and dom variables // for the rest of the function... };
This is an extremely simple pattern, but at the same time it has numerous benefits:
• Explicit declaration of dependencies signals to the users of your code the specific script files that they need to make sure are included in the page.
• Upfront declaration at the top of the function makes it easy to find and resolve dependencies.
• Working with a local variable (such as dom) is always faster than working with a global (such as YAHOO) and even faster than working with nested properties of a global variable (such as YAHOO.util.Dom), resulting in better performance. When following this dependency declaration pattern, the global symbol resolution is performed only once in the function. After that the local variable is used, which is much faster.
• Advanced minification tools such as YUICompressor and Google Closure compiler will rename local variables (so event will likely become just one character such as A), resulting in smaller code, but never global variables, because it’s not safe to do so.
- Private Properties and Methods
JavaScript has no special syntax to denote private, protected, or public properties and methods, unlike Java or other languages. All object members are public:var myobj = { myprop: 1, getProp: function () { return this.myprop; } }; console.log(myobj.myprop); // `myprop` is publicly accessible console.log(myobj.getProp()); // getProp() is public too
The same is true when you use constructor functions to create objects; all members are still public:function Gadget() { this.name = 'iPod'; this.stretch = function () { return 'iPad'; }; } var toy = new Gadget(); console.log(toy.name); // `name` is public console.log(toy.stretch()); // stretch() is public
Although the language doesn’t have special syntax for private members, you can implement them using a closure. Your constructor functions create a closure and any variables that are part of the closure scope are not exposed outside the constructor. However, these private variables are available to the public methods: methods defined inside the constructor and exposed as part of the returned objects. Let’s see an example where name is a private member, not accessible outside the constructor:function Gadget() { // private member var name = 'iPod'; // public function this.getName = function () { return name; }; } var toy = new Gadget(); // `name` is undefined, it's private console.log(toy.name); // undefined // public method has access to `name` console.log(toy.getName()); // "iPod"
As you can see, it’s easy to achieve privacy in JavaScript. All you need to do is wrap the data you want to keep private in a function and make sure it’s local to the function, which means not making it available outside the function.
- Privileged Methods
The notion of privileged methods doesn’t involve any specific syntax; it’s just a name given to the public methods that have access to the private members (and hence have more privileges).
In the previous example, getName() is a privileged method because it has “special” access to the private property name.
- Privacy Failures
There are some edge cases when you’re concerned about privacy:
• Some earlier versions of Firefox enable a second parameter to be passed to eval() that is a context object enabling you to sneak into the private scope of the function. Similarly the __parent__ property in Mozilla Rhino would enable you access to private Scope. These edge cases don’t apply to widely used browsers today.
• When you’re directly returning a private variable from a privileged method and this variable happens to be an object or array, then outside code can modify the private variable because it’s passed by reference.
Let’s examine the second case a little more closely. The following implementation of Gadget looks innocent:function Gadget() { // private member var specs = { screen_width: 320, screen_height: 480, color: "white" }; // public function this.getSpecs = function () { return specs; }; }
The problem here is that getSpecs() returns a reference to the specs object. This enables the user of Gadget to modify the seemingly hidden and private specs; The solution to this unexpected behavior is to be careful not to pass references to objects and arrays you want to keep private. One way to achieve this is to have getSpecs() return a new object containing only some of the data that could be interesting to the consumer of the object. This is also known as Principle of Least Authority (POLA), which states that you should never give more than needed. In this case, if the consumer of Gadget is interested whether the gadget fits a certain box, it needs only the dimensions.
So instead of giving out everything, you can create getDimensions(), which returns a new object containing only width and height. You may not need to implement getSpecs() at all.
Another approach, when you need to pass all the data, is to create a copy of the specs object, Using a general-purpose object-cloning function.
- Revealing Private Functions As Public Methods
The revelation pattern is about having private methods, which you also expose as public methods. This could be useful when all the functionality in an object is critical for the workings of the object and you want to protect it as much as possible. But at the same time you want to provide public access to some of this functionality because that could be useful, too. When you expose methods publicly, you make them vulnerable; some of the users of your public API may modify it, even involuntarily. In ECMAScript 5 you have the option to freeze an object, but not in the previous versions of the language. Enter the revelation pattern (the term coined by Christian Heilmann originally was “revealing module pattern”).
Let’s take an example, building on top of one of the privacy patterns—the private members in object literals:var myarray; (function () { var astr = "[object Array]", toString = Object.prototype.toString; function isArray(a) { return toString.call(a) === astr; } function indexOf(haystack, needle) { var i = 0, max = haystack.length; for (; i < max; i += 1) { if (haystack[i] === needle) { return i; } } return −1; } myarray = { isArray: isArray, indexOf: indexOf, inArray: indexOf }; }());
Here you have two private variables and two private functions—isArray() and indexOf(). Toward the end of the immediate function, the object myarray is populated with the functionality you decide is appropriate to make publicly available. In this case the same private indexOf() is exposed as both ECMAScript 5–style indexOf and PHPinspired inArray. Testing the new myarray object:myarray.isArray([1,2]); // true myarray.isArray({0: 1}); // false myarray.indexOf(["a", "b", "z"], "z"); // 2 myarray.inArray(["a", "b", "z"], "z"); // 2
- Module Pattern
The module pattern is widely used because it provides structure and helps organize your code as it grows. Unlike other languages, JavaScript doesn’t have special syntax for packages, but the module pattern provides the tools to create self-contained decoupled pieces of code, which can be treated as black boxes of functionality and added, replaced, or removed according to the (ever-changing) requirements of the software you’re writing.
The module pattern is a combination of several patterns described so far in the book,namely:• Namespaces • Immediate functions • Private and privileged members • Declaring dependencies
The first step is setting up a namespace. Let’s use the namespace() function from earlier in this chapter and start an example utility module that provides useful array methods:MYAPP.namespace('MYAPP.utilities.array');
The next step is defining the module. The pattern uses an immediate function that will provide private scope if privacy is needed. The immediate function returns an object—the actual module with its public interface, which will be available to the consumers of the module:MYAPP.utilities.array = (function () { return { // todo... }; }());
Next, let’s add some methods to the public interface:MYAPP.utilities.array = (function () { return { inArray: function (needle, haystack) { // ... }, isArray: function (a) { // ... } }; }());
Using the private scope provided by the immediate function, you can declare some private properties and methods as needed. Right at the top of the immediate function will also be the place to declare any dependencies your module might have. Following the variable declarations, you can optionally place any one-off initialization code that helps set up the module. The final result is an object returned by the immediate function that contains the public API of your module:MYAPP.namespace('MYAPP.utilities.array'); MYAPP.utilities.array = (function () { // dependencies var uobj = MYAPP.utilities.object, ulang = MYAPP.utilities.lang, // private properties array_string = "[object Array]", ops = Object.prototype.toString; // private methods // ... // end var // optionally one-time init procedures // ... // public API return { inArray: function (needle, haystack) { for (var i = 0, max = haystack.length; i < max; i += 1) { if (haystack[i] === needle) { return true; } } }, isArray: function (a) { return ops.call(a) === array_string; } // ... more methods and properties }; }());
The module pattern is a widely used and highly recommended way to organize your code, especially as it grows.
- Sandbox Pattern
The sandbox pattern addresses the drawbacks of the namespacing pattern, namely :
• Reliance on a single global variable to be the application’s global. In the namespacing pattern, there is no way to have two versions of the same application or library run on the same page, because they both need the same global symbol name, for example, MYAPP.
• Long, dotted names to type and resolve at runtime. for example, MYAPP.utilities.array.
As the name suggests, the sandbox pattern provides an environment for the modules to “play” without affecting other modules and their personal sandboxes. The pattern is heavily used in YUI version 3, for example, but keep in mind that the following discussion is a sample reference implementation and does not attempt to describe how YUI3’s sandbox implementation works.
A Global Constructor
In the namespacing pattern you have one global object; in the sandbox pattern the single global is a constructor: let’s call it Sandbox(). You create objects using this constructor, and you also pass a callback function, which becomes the isolated sandboxed environment for your code. Using the sandbox will look like this:new Sandbox(function (box) { // your code here... });
The object box will be like MYAPP in the namespacing example—it will have all the library functionality you need to make your code work. Let’s add two more things to the pattern:
• With some magic (enforcing new pattern from Chapter 3), you can assume New and not require it when creating the object.
• The Sandbox() constructor can accept an additional configuration argument (or arguments) specifying names of modules required for this object instance. We want the code to be modular, so most of the functionality Sandbox() provides will be contained in modules.
With these two additional features, let’s see some examples of what the code for instantiating objects will look like. You can omit new and create an object that uses some fictional “ajax” and “event” modules like so:Sandbox(['ajax', 'event'], function (box) { // console.log(box); });
This example is similar to the preceding one, but this time module names are passed as individual arguments:Sandbox('ajax', 'dom', function (box) { // console.log(box); });
And how about using a wildcard “*” argument to mean “use all available modules”? For convenience, let’s also say that when no modules are passed, the sandbox will assume '*'. So two ways to use all available modules will be like:Sandbox('*', function (box) { // console.log(box); }); Sandbox(function (box) { // console.log(box); });
And one more example of using the pattern illustrates how you can instantiate sandbox objects multiple times—and you can even nest them one within the other without the two interfering:Sandbox('dom', 'event', function (box) { // work with dom and event Sandbox('ajax', function (box) { // another sandboxed "box" object // this "box" is not the same as // the "box" outside this function //... // done with Ajax }); // no trace of Ajax module here });
As you can see from these examples, when using the sandbox pattern, you can protect the global namespace by having your code wrapped into callback functions. If you need, you can also use the fact that functions are objects and store some data as “static” properties of the Sandbox() constructor. And, finally, you can have different instances depending on the type of modules you need and those instances work independently of each other.
Now let’s see how you can approach implementing the Sandbox() constructor and its modules to support all this functionality.
Adding Modules
Before implementing the actual constructor, let’s see how we can approach adding modules.
The Sandbox() constructor function is also an object, so you can add a static property called modules to it. This property will be another object containing key-value pairs where the keys are the names of the modules and the values are the functions that implement each module:Sandbox.modules = {}; Sandbox.modules.dom = function (box) { box.getElement = function () {}; box.getStyle = function () {}; box.foo = "bar"; }; Sandbox.modules.event = function (box) { // access to the Sandbox prototype if needed: // box.constructor.prototype.m = "mmm"; box.attachEvent = function () {}; box.dettachEvent = function () {}; }; Sandbox.modules.ajax = function (box) { box.makeRequest = function () {}; box.getResponse = function () {}; };
In this example we added modules dom, event, and ajax, which are common pieces of functionality in every library or complex web application.The functions that implement each module accept the current instance box as a parameter and may add additional properties and methods to that instance.
Implementing the Constructor
Finally, let’s implement the Sandbox() constructor (naturally, you would want to rename this type of constructor to something that makes sense for your library or application):function Sandbox() { // turning arguments into an array var args = Array.prototype.slice.call(arguments), // the last argument is the callback callback = args.pop(), // modules can be passed as an array or as individual parameters modules = (args[0] && typeof args[0] === "string") ? args : args[0], i; // make sure the function is called // as a constructor if (!(this instanceof Sandbox)) { return new Sandbox(modules, callback); } // add properties to `this` as needed: this.a = 1; this.b = 2; // now add modules to the core `this` object // no modules or "*" both mean "use all modules" if (!modules || modules === '*') { modules = []; for (i in Sandbox.modules) { if (Sandbox.modules.hasOwnProperty(i)) { modules.push(i); } } } // initialize the required modules for (i = 0; i < modules.length; i += 1) { Sandbox.modules[modules[i]](this); } // call the callback callback(this); } // any prototype properties as needed Sandbox.prototype = { name: "My Application", version: "1.0", getName: function () { return this.name; } };
The key items in the implementation are:
• There’s a check whether this is an instance of Sandbox and if not (meaning Sandbox() was called without new), we call the function again as a constructor.
• You can add properties to this inside the constructor. You can also add properties to the prototype of the constructor.
• The required modules can be passed as an array of module names, or as individual arguments, or with the * wildcard (or omitted), which means we should load all available modules. Notice that in this example implementation we don’t worry about loading required functionality from additional files, but that’s definitely an option. This is something supported by YUI3 for example. You can load only the most basic module (also known as a “seed”) and whatever modules you require will be loaded from external files using a naming convention where the filenames correspond to module names.
• When we know the required modules, we initialize them, which means we call the function that implements each module.
• The last argument to the constructor is the callback. The callback will be invoked at the end using the newly created instance. This callback is actually the user’s sandbox, and it gets a box object populated with all the requested functionality.
- Static Members
Static properties and methods are those that don’t change from one instance to another.In class-based languages, static members are created using special syntax and then used as if they were members of the class itself. For example, a static method max() of some MathUtils class would be invoked like MathUtils.max(3, 5). This is an example of a public static member, which can be used without having to create an instance of the class. There can also be private static members—not visible to the consumer of the class but still shared among all the instances of the class. Let’s see how to implement both private and public static members in JavaScript.
Public Static Members
In JavaScript there’s no special syntax to denote static members. But you can have the same syntax as in a “classy” language by using a constructor function and adding properties to it. This works because constructors, like all other functions, are objects and they can have properties. The memoization pattern discussed in the previous chapter employed the same idea—adding properties to a function.
The following example defines a constructor Gadget with a static method isShiny() and a regular instance method setPrice(). The method isShiny() is a static method because it doesn’t need a specific gadget object to work (just like you don’t need a particular gadget to figure out that all gadgets are shiny). setPrice(), on the other hand,needs an object, because gadgets can be priced differently:// constructor var Gadget = function () {}; // a static method Gadget.isShiny = function () { return "you bet!"; // 没错 }; // a normal method added to the prototype Gadget.prototype.setPrice = function (price) { this.price = price; }; /* Now let’s call these methods. The static isShiny() is invoked directly on the constructor, whereas the regular method needs an instance: */ // calling a static method Gadget.isShiny(); // "you bet" // creating an instance and calling a method var iphone = new Gadget(); iphone.setPrice(500); typeof Gadget.setPrice; // "undefined" typeof iphone.isShiny; // "undefined"
Attempting to call an instance method statically won’t work; same for calling a static method using the instance iphone object
Sometimes it could be convenient to have the static methods working with an instance too. This is easy to achieve by simply adding a new method to the prototype, which serves as a façade pointing to the original static method:Gadget.prototype.isShiny = Gadget.isShiny; window.alert(iphone.isShiny()); // "you bet"
In such cases you need to be careful if you use this inside the static method. When you do Gadget.isShiny() then this inside isShiny() will refer to the Gadget constructor function. If you do iphone.isShiny() then this will point to iphone(!).
One last example shows how you can have the same method being called statically and nonstatically and behave slightly different, depending on the invocation pattern. Here instanceof helps determine how the method was called:// constructor var Gadget = function (price) { this.price = price; }; // a static method Gadget.isShiny = function () { // this always works var msg = "you bet"; if (this instanceof Gadget) { // this only works if called non-statically msg += ", it costs $" + this.price + '!'; } return msg; }; // a normal method added to the prototype Gadget.prototype.isShiny = function () { return Gadget.isShiny.call(this); }; // Testing a static method call: Gadget.isShiny(); // "you bet" //Testing an instance, nonstatic call: var a = new Gadget('499.99'); a.isShiny(); // "you bet, it costs $499.99!"
Private Static Members
The discussion so far was on public static methods; now let’s take a look at how you can implement private static members. By private static members, we mean members that are:
• Shared by all the objects created with the same constructor function
• Not accessible outside the constructor
Let’s look at an example where counter is a private static property in the constructor Gadget. In this chapter there was already a discussion on private properties, so this part is still the same—you need a function to act as a closure and wrap around the private members. Then let’s have the same wrapper function execute immediately and return a new function. The returned function value is assigned to the variable Gadget and becomes the new constructor:var Gadget = (function () { // static variable/property var counter = 0; // returning the new implementation // of the constructor return function () { console.log(counter += 1); }; }()); // execute immediately
The new Gadget constructor simply increments and logs the private counter. Testing with several instances you can see that counter is indeed shared among all instances; Because we’re incrementing the counter with one for every object, this static property becomes an ID that uniquely identifies each object created with the Gadget constructor. The unique identifier could be useful, so why not expose it via a privileged method? Below is an example that builds upon the previous and adds a privileged method getLastId() to access the static private property:// constructor var Gadget = (function () { // static variable/property var counter = 0, NewGadget; // this will become the // new constructor implementation NewGadget = function () { counter += 1; }; // a privileged method NewGadget.prototype.getLastId = function () { return counter; }; // overwrite the constructor return NewGadget; }()); // execute immediately // Testing the new implementation: var iphone = new Gadget(); iphone.getLastId(); // 1 var ipod = new Gadget(); ipod.getLastId(); // 2 var ipad = new Gadget(); ipad.getLastId(); // 3
Static properties (both private and public) can be quite handy. They can contain methods and data that are not instance-specific and don’t get re-created with every instance.
发表评论
-
High Performance JavaScript 读书笔记(五)
2011-02-27 21:24 2276五.Strings and Regular Expressio ... -
High Performance JavaScript 读书笔记(六)
2011-02-27 20:49 2662六.Responsive Interfaces There ... -
High Performance JavaScript 读书笔记(四)
2011-02-27 19:50 1216四.Algorithms and Flow Control ... -
High Performance JavaScript 读书笔记(三)
2011-02-27 14:43 1728三.DOM Scripting DOM scripting ... -
High Performance JavaScript 读书笔记(一)
2011-02-27 13:44 1613一.Loading and Execution JavaS ... -
JavaScript 数据访问(翻译自High Performance Javascript 第二章)
2011-02-27 13:21 1933计算机科学中一 ... -
JavaScript Patterns 读书笔记(七)
2011-02-15 20:32 14447.Client Pattern DOM Access ... -
JavaScript Patterns 读书笔记(六)
2011-02-15 19:38 12636.Design Pattern Singleton ... -
JavaScript Patterns 读书笔记(五)
2011-02-15 19:08 12345.Inheritance Pattern Classic ... -
JavaScript Patterns 读书笔记(二)
2011-02-14 21:20 1166二.Object Object Constructor C ... -
JavaScript Patterns 读书笔记(三)
2011-02-14 21:19 1465三.Function Background The ... -
JavaScript Patterns 读书笔记(一)
2011-02-14 20:09 1664一.Global 全局域中的this = window.m ... -
JavaScript: The Good Parts 读书笔记(五)
2011-01-27 12:56 2093五.Javascript 总结 语 ... -
JavaScript: The Good Parts 读书笔记(四)
2011-01-27 11:37 1003四.数组与正则表达式 ... -
JavaScript: The Good Parts 读书笔记(三)
2011-01-26 23:38 1410三.继承 概述 Javascr ... -
JavaScript: The Good Parts 读书笔记(二)
2011-01-26 23:01 1784二.函数 JS 中函数亦是对象 使用字面变量表面 ... -
JavaScript: The Good Parts 读书笔记(一)
2011-01-26 21:44 1291一.基础特性 在浏览器中,每个<script> ...
相关推荐
其次,笔记可能会深入讲解设计模式(Design Patterns),这是软件设计中的重要概念,如工厂模式、单例模式、观察者模式等。这些模式为解决常见的软件设计问题提供了标准化的解决方案,是提高代码复用性和灵活性的...
这篇博客涵盖了前端开发的多个重要知识点,包括心法、LeetCode算法练习、框架原理、计算机网络、设计模式、自造轮子以及读书笔记等。以下是对这些内容的详细阐述: **心法**: 在前端开发中,心法指的是开发者应该...
它包含一些经典的GoF设计模式的集合,这些模式使用JavaScript和ES6类以及Node.js API在JavaScript中实现。 感谢并非常欢迎您做出贡献,调整现有模式的README.md,或改进示例或添加新模式。 只需做出一个叉子,进行...
本笔记主要依据曾探的著作《JavaScript设计模式与开发实践》进行整理,涵盖了设计模式的基本知识,以及创建、结构、行为、状态和策略等模式的应用。 **基础知识** 在深入设计模式之前,我们需要理解一些基本概念,...
2. `languages/` - 不同编程语言的学习笔记,如Python、Java、JavaScript等。 3. `frameworks/` - 使用的各种框架的笔记,如Django、React、Angular等。 4. `algorithms/` - 数据结构和算法的学习笔记,包括实现和...
2. **GWT_speakernoted.pdf**:这可能是关于Google Web Toolkit (GWT)的演讲笔记,GWT是一个开源的Java开发工具,它允许开发者使用Java编写客户端Web应用,然后编译成优化的JavaScript代码。GWT支持Ajax特性,并且...
8. **Design_Patterns**:讨论软件设计模式,如单例模式、工厂模式等在前端开发中的应用。 9. **Interview_Tips**:提供面试技巧,如何回答行为问题,如何展示自己的项目经验等。 10. **Projects**:可能包含一些...
都是参考众多文章归纳整理学习而写的,文章包括了HTML基础、CSS基础、JavaScript基础与拓展、Browser浏览器相关、Vue使用与分析、React使用与分析、Plugin插件相关、Patterns设计模式、Linux命令、LeetCode题解等...
都是参考众多文章归纳整理学习而写的,文章包括了HTML基础、CSS基础、JavaScript基础与拓展、Browser浏览器相关、Vue使用与分析、React使用与分析、Plugin插件相关、Patterns设计模式、Linux命令、LeetCode题解等...
除了每日一题的学习笔记之外还有一些做项目时的记录以及遇到的坑等,对于技术相关的文章基本都是参考众多文章归纳整理学习而写的,文章包括了HTML基础、CSS基础、JavaScript基础与拓展、Browser浏览器相关、Vue使用...
项目介绍小路描述CSS CSS世界练习代码UIAndAnamited 画布,SVG,三等练习代码算法算法练习成分组件封装练习源代码原始解析笔记数据结构斑点结构DesignPatterns |设计模式演示自己实现的一些好玩的小演示
女性笔记 :clapping_hands:欢迎star,也不容易搞丢链接哦! :clapping_hands: 欢迎加入明星,失去联系并不容易!它是什么?我是在参加2020年秋招的时候,实际上那时候往前2个月我才开始系统接触前沿领域。为了快速...
单页图书项目使用项目的IT笔记(Java,Linux,密码学,云,体系结构等)的超级备忘单。克隆并执行下一行以启动本地Web服务器。 $ ./httpServer.py仅需要服务器,以避免浏览器禁用从文件系统路径加载脚本的麻烦。 ...