- 浏览: 45770 次
- 性别:
- 来自: 湖南
最新评论
-
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 第二章)
三.Function
- Background
There are two main features of the functions in JavaScript that make them special—the first is that functions are first-class objects and the second is that they provide scope.Functions are objects that:- Can be created dynamically at runtime, during the execution of the program.
- Can be assigned to variables, can have their references copied to other variables, can be augmented, and, except for a few special cases, can be deleted.
- Can be passed as arguments to other functions and can also be returned by other functions.
- Can have their own properties and methods.
In general, when you think of a function in JavaScript, think of an object, with the only special feature that this object is invokable, meaning it can be executed.The fact that functions are objects becomes obvious when you see the new Function() constructor in action:
// antipattern // for demo purposes only var add = new Function('a, b', 'return a + b'); add(1, 2); // returns 3
In this code, there’s no doubt that add() is an object; after all it was created by a constructor. Using the Function() constructor is not a good idea though (it’s as bad as eval()) because code is passed around as a string and evaluated. It’s also inconvenient to write (and read) because you have to escape quotes and take extra care if you want to properly indent the code inside the function for readability. The second important feature is that functions provide scope. In JavaScript there’s no curly braces local scope(块级作用域,curly brace=大括号); in other words, blocks don’t create scope. There’s only function scope. Any variable defined with var inside of a function is a local variable, invisible outside the function. Saying that curly braces don’t provide local scope means that if you define a variable with var inside of an if condition or inside of a for or a while loop, that doesn’t mean the variable is local to that if or for. It’s only local to the wrapping function, and if there’s no wrapping function, it becomes a global variable.
- Disambiguation of Terminology (消除术语上的歧义)
Let’s take a moment to discuss the terminology surrounding the code used to define a function, because using accurate and agreed-upon names is just as important as the code when talking about patterns. Consider the following snippet:// named function expression var add = function add(a, b) { return a + b; };
The preceding code shows a function, which uses a named function expression. If you skip the name (the second add in the example) in the function expression, you get an unnamed function expression, also known as simply as function expression or most commonly as an anonymous function. An example is:
// function expression, a.k.a. anonymous function var add = function (a, b) { return a + b; };
So the broader term is “function expression” and the “named function expression” is a specific case of a function expression, which happens to define the optional name. When you omit the second add and end up with an unnamed function expression, this won’t affect the definition and the consecutive invocations of the function. The only difference is that the name property of the function object will be a blank string. The name property is an extension of the language (it’s not part of the ECMA standard) but widely available in many environments. If you keep the second add, then the property add.name will contain the string “add.” The name property is useful when using debuggers, such as Firebug, or when calling the same function recursively from itself; otherwise you can just skip it.
Finally, you have function declarations. They look the most similar to functions used in other languages:function foo() { // function body goes here }
In terms of syntax, named function expressions and function declarations look similar,especially if you don’t assign the result of the function expression to a variable (as we’ll see in the callback pattern further in the chapter). Sometimes there’s no other way to tell the difference between a function declaration and a named function expression other than looking at the context in which the function occurs, as you’ll see in the next section.
There’s syntax difference between the two in the trailing semicolon(分号). The semicolon is not needed in function declarations but is required in function expressions, and you should always use it even though the automatic semicolon insertion mechanism might do it for you.
- Declarations Versus Expressions: Names and Hoisting
So what should you use—function declarations or function expressions? In cases in which syntactically you cannot use a declaration, this dilemma is solved for you. Examples include passing a function object as a parameter or defining methods in object literals:// this is a function expression, // pased as an argument to the function `callMe` callMe(function () { // I am an unnamed function expression // also known as an anonymous function }); // this is a named function expression callMe(function me() { // I am a named function expression // and my name is "me" }); // another function expression var myobject = { say: function () { // I am a function expression } };
Function declarations can only appear in “program code,” meaning inside of the bodies of other functions or in the global space. Their definitions cannot be assigned to variables or properties, or appear in function invocations as parameters. Here’s an example of the allowed usage of function declarations, where all the functions foo(), bar(), and local() are defined using the function declaration pattern: (只有在函数体内和全局范围内才可以声明函数(!))// global scope function foo() {} function local() { // local scope function bar() {} return bar; }
- Function Hoisting(函数提升)
From the previous discussion you may conclude that the behavior of function declarations is pretty much equivalent to a named function expression. That’s not exactly true, and a difference lies in the hoisting behavior.
As you know, all variables, no matter where in the function body they are declared, get hoisted to the top of the function behind the scenes. The same applies for functions because they are just objects assigned to variables. The only “gotcha” is that when using a function declaration, the definition of the function also gets hoisted, not only its declaration. Consider this snippet:// antipattern // for illustration only // global functions function foo() { alert('global foo'); } function bar() { alert('global bar'); } function hoistMe() { console.log(typeof foo); // "function" console.log(typeof bar); // "undefined" foo(); // "local foo" bar(); // TypeError: bar is not a function // function declaration: // variable 'foo' and its implementation both get hoisted function foo() { alert('local foo'); } // function expression: // only variable 'bar' gets hoisted // not the implementation var bar = function () { alert('local bar'); }; } hoistMe();
In this example you see that, just like with normal variables, the mere presence of foo and bar anywhere in the hoistMe() function moves them to the top, overwriting the global foo and bar. The difference is that local foo()’s definition is hoisted to the top and works fine; although it’s defined later. The definition of bar() is not hoisted, only its declaration. That’s why until the code execution reaches bar()’s definition, it’s undefined and not usable as a function (while still preventing the global bar() from being “seen” in the scope chain).
Now that the required background and terminology surrounding functions is out of the way, let’s see some of the good patterns related to functions that JavaScript has to offer, starting with the callback pattern. Again, it’s important to remember the two special features of the functions in JavaScript:• They are objects. • They provide local scope.
- Function’s name Property
Another thing to consider when choosing a function definition pattern is the availability of the read-only name property. Again, this property is not standard but available in many environments. In function declarations and named function expressions, the name property is defined. In anonymous function expressions,
it depends on the implementation; it could be undefined (IE) or defined with an empty string (Firefox,WebKit):function foo() {} // declaration var bar = function () {}; // expression var baz = function baz() {}; // named expression foo.name; // "foo" bar.name; // "" or undefined baz.name; // "baz"
The name property is useful when debugging code in Firebug or other debuggers. When the debugger needs to show you an error in a function, it can check for the presence of the name property and use it as an indicator. The name property is also used to call the same function recursively from within itself. If you were not interested in these two cases, then an unnamed function expression would be easier and less verbose. The case against function declarations and the reason to prefer function expressions is that the expressions highlight that functions are objects like all other objects and not some special language construct.
It’s technically possible to use a named function expression and assign it to a variable with a different name, for example:var foo = function bar() {};
However, the behavior of this usage is not properly implemented in some browsers (IE), so it’s not recommended to use this pattern.
- Self-Defining Functions
Functions can be defined dynamically and can be assigned to variables. If you create a new function and assign it to the same variable that already holds another function, you’re overwriting the old function with the new one. In a way, you’re recycling the old function pointer to point to a new function. And all this can happen inside the body of the old function. In this case the function overwrites and redefines itself with a new implementation. This probably sounds more complicated than it is; let’s take a look at a simple example:
var scareMe = function () { alert("Boo!"); scareMe = function () { alert("Double boo!"); }; }; // using the self-defining function scareMe(); // Boo! scareMe(); // Double boo!
This pattern is useful when your function has some initial preparatory work to do and it needs to do it only once. Because there’s no reason to do repeating work when it can be avoided, a portion of the function may no longer be required. In such cases, the selfdefining function can update its own implementation.Using this pattern can obviously help with the performance of your application, because your redefined function simply does less work.
A drawback of the pattern is that any properties you’ve previously added to the original function will be lost when it redefines itself. Also if the function is used with a different name, for example, assigned to a different variable or used as a method of an object,then the redefinition part will never happen and the original function body will be executed.
Let’s see an example where the scareMe() function is used in a way that a first-class object would be used:
1. A new property is added.
2. The function object is assigned to a new variable.
3. The function is also used as a method.
Consider the following snippet:// 1. adding a new property scareMe.property = "properly"; // 2. assigning to a different name var prank = scareMe; // 3. using as a method var spooky = { boo: scareMe }; // calling with a new name prank(); // "Boo!" prank(); // "Boo!" console.log(prank.property); // "properly" // calling as a method spooky.boo(); // "Boo!" spooky.boo(); // "Boo!" console.log(spooky.boo.property); // "properly" // using the self-defined function scareMe(); // Double boo! scareMe(); // Double boo! console.log(scareMe.property); // undefined
As you can see, the self-definition didn’t happen as you probably expected when the function was assigned to a new variable. Every time prank() was called, it alerted “Boo!” At the same time it overwrote the global scareMe() function, but prank() itself kept seeing the old definition including the property property. The same happened when the function was used as the boo() method of the spooky object. All these invocations kept rewriting the global scareMe() pointer so that when it was eventually called, it had the updated body alerting “Double boo” right from the first time. It was also no longer able to see scareMe.property.
- Immediate Functions
The immediate function pattern is a syntax that enables you to execute a function as soon as it is defined. Here’s an example:(function () { alert('watch out!'); }());
This pattern is in essence just a function expression (either named or anonymous),which is executed right after its creation. The term immediate function is not defined in the ECMAScript standard, but it’s short and helps describe and discuss the pattern. The pattern consists of the following parts:• You define a function using a function expression. (A function declaration won’t work.) • You add a set of parentheses at the end, which causes the function to be executed immediately. • You wrap the whole function in parentheses (required only if you don’t assign the function to a variable).
The following alternative syntax is also common (note the placement of the closing parentheses), but JSLint prefers the first one:(function () { alert('watch out!'); })();
This pattern is useful because it provides a scope sandbox for your initialization code.
Think about the following common scenario: Your code has to perform some setup tasks when the page loads, such as attaching event handlers, creating objects, and so on. All this work needs to be done only once, so there’s no reason to create a reusable named function. But the code also requires some temporary variables, which you won’t need after the initialization phase is complete. It would be a bad idea to create all those variables as globals. That’s why you need an immediate function—to wrap all your code in its local scope and not leak any variables in the global scope:(function () { var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], today = new Date(), msg = 'Today is ' + days[today.getDay()] + ', ' + today.getDate(); alert(msg); }()); // "Today is Fri, 13"
If this code weren’t wrapped in an immediate function, then the variables days, today, and msg would all be global variables, leftovers from the initialization code.
You can also pass arguments to immediate functions, as the following example demonstrates:// prints: (function (who, when) { console.log("I met " + who + " on " + when); }("Joe Black", new Date()));
Commonly, the global object is passed as an argument to the immediate function so that it’s accessible inside of the function without having to use window: this way makes the code more interoperable in environments outside the browser:(function (global) { // access the global object via `global` }(this));
Note that in general you shouldn’t pass too many parameters to an immediate function, because it could quickly become a burden to constantly scroll to the top and to the bottom of the function to understand how it works.
Just like any other function, an immediate function can return values and these return values can be assigned to variables:var result = (function () { return 2 + 2; }());
Another way to achieve the same is to omit the parentheses that wrap the function,because they are not required when you assign the return value of an immediate function to a variable(!). Omitting the first set of parentheses gives you the following:var result = function () { return 2 + 2; }();
This syntax is simpler, but it may look a bit misleading. Failing to notice the () at the end of the function, someone reading the code might think that result points to a function. Actually result points to the value returned by the immediate function, in this case the number 4. Yet another syntax that accomplishes the same results is:var result = (function () { return 2 + 2; })();
The previous examples returned a primitive integer value as the result of executing the immediate function. But instead of a primitive value, an immediate function can return any type of value, including another function. You can then use the scope of the immediate function to privately store some data, specific to the inner function you return.
In the next example, the value returned by the immediate function is a function, which will be assigned to the variable getResult and will simply return the value of res, a value that was precomputed and stored in the immediate function’s closure:var getResult = (function () { var res = 2 + 2; return function () { return res; }; }());
Immediate functions can also be used when you define object properties. Imagine you need to define a property that will likely never change during the life of the object, but before you define it a bit of work needs to be performed to figure out the right value. You can use an immediate function to wrap that work and the returned value of the immediate function will become the value of the property. The following code shows an example:var o = { message: (function () { var who = "me", what = "call"; return what + " " + who; }()), getMsg: function () { return this.message; } }; // usage o.getMsg(); // "call me" o.message; // "call me"
In this example, o.message is a string property, not a function, but it needs a function,which executes while the script is loading and which helps define the property.
- Immediate Object Initialization
Another way to protect from global scope pollution, similar to the immediate functions pattern previously described, is the following immediate object initialization pattern.This pattern uses an object with an init() method, which is executed immediately after the object is created. The init() function takes care of all initialization tasks.Here’s an example of the immediate object pattern:({ // here you can define setting values // a.k.a. configuration constants maxwidth: 600, maxheight: 400, // you can also define utility methods gimmeMax: function () { return this.maxwidth + "x" + this.maxheight; }, // initialize init: function () { console.log(this.gimmeMax()); // more init tasks... } }).init();
In terms of syntax, you approach this pattern as if you’re creating a normal object using the object literal. You also wrap the literal in parentheses (grouping operator), which instructs the JavaScript engine to treat the curly braces as object literal, not as a code block. (It’s not an if or a for loop.) After you close the parentheses, you invoke the init() method immediately.
You can also wrap the object and the init() invocation into grouping parentheses instead of wrapping the object only. In other words, both of these work:({...}).init(); ({...}.init());
The benefits of this pattern are the same as the immediate function pattern: you protect the global namespace while performing the one-off initialization tasks. It may look a little more involved in terms of syntax compared to just wrapping a bunch of code in an anonymous function, but if your initialization tasks are more complicated (as they often are) it adds structure to the whole initialization procedure. For example, private helper functions are clearly distinguishable because they are properties of the temporary object, whereas in an immediate function pattern, they are likely to be just functions scattered around.
A drawback of this pattern is that most JavaScript minifiers may not minify this pattern as efficiently as the code simply wrapped into a function. The private properties and methods will not be renamed to shorter names because, from a minifier’s point of view, it’s not trivial to do so safely. At the moment of writing, Google’s Closure Compiler in “advanced” mode is the only minifier that renames the immediate object’s properties to shorter names, turning the preceding example into something like:({d:600,c:400,a:function(){return this.d+"x"+this.c},b:function(){console.log(this.a())}}).b();
- Init-Time Branching
Init-time branching (also called load-time branching) is an optimization pattern. When you know that a certain condition will not change throughout the life of the program,it makes sense to test the condition only once. Browser sniffing (or feature detection) is a typical example.
For example, after you’ve sniffed that XMLHttpRequest is supported as a native object,there’s no chance that the underlying browser will change in the middle of your program execution and all of a sudden you’ll need to deal with ActiveX objects. Because the environment doesn’t change, there’s no reason for your code to keep sniffing (and reaching the same conclusion) every time you need another XHR object. Figuring out the computed styles of a DOM element or attaching event handlers are other candidates that can benefit from the init-time branching pattern. Most developers have coded—at least once in their client-side programming life—a utility with methods for attaching and removing event listeners, like in the following example:// BEFORE var utils = { addListener: function (el, type, fn) { if (typeof window.addEventListener === 'function') { // Mozilla el.addEventListener(type, fn, false); } else if (typeof document.attachEvent === 'function') { // IE el.attachEvent('on' + type, fn); } else { // older browsers el['on' + type] = fn; } }, removeListener: function (el, type, fn) { // pretty much the same... } };
The problem with this code is that it’s a bit inefficient. Every time you call utils.addListener() or utils.removeListener(), the same checks get executed over and over again.
Using init-time branching, you sniff the browser features once, during the initial loading of the script. At that time you redefine how the function will work throughout the lifespan of the page. The following is an example of how you can approach this task:// AFTER // the interface var utils = { addListener: null, removeListener: null }; // the implementation if (typeof window.addEventListener === 'function') { // Mozilla utils.addListener = function (el, type, fn) { el.addEventListener(type, fn, false); }; utils.removeListener = function (el, type, fn) { el.removeEventListener(type, fn, false); }; } else if (typeof document.attachEvent === 'function') { // IE utils.addListener = function (el, type, fn) { el.attachEvent('on' + type, fn); }; utils.removeListener = function (el, type, fn) { el.detachEvent('on' + type, fn); }; } else { // older browsers utils.addListener = function (el, type, fn) { el['on' + type] = fn; }; utils.removeListener = function (el, type, fn) { el['on' + type] = null; }; }
Here is the moment to mention a word of caution against browser sniffing(测错). When you use this pattern, don’t over-assume browser features. For example, if you’ve sniffed that the browser doesn’t support window.addEventListener, don’t just assume the browser you’re dealing with is IE and it doesn’t support XMLHttpRequest natively either, although it was true at some point in the browser’s history. There might be cases in which you can safely assume that features go together, such as .addEventListener and .removeEventListener, but in general browser features change independently. The best strategy is to sniff features separately and then use load-time branching to do the sniffing only once.
- Function Properties—A Memoization Pattern
Functions are objects, so they can have properties. In fact, they do have properties and methods out-of-the-box. For example, every function, no matter what syntax you use to create it, automatically gets a length property containing the number of arguments the function expects:function func(a, b, c) {} console.log(func.length); // 3
You can add custom properties to your functions at any time. One use case for custom properties is to cache the results (the return value) of a function, so the next time the function is called, it doesn’t have to redo potentially heavy computations. Caching the results of a function is also known as memoization.
In the following example, the function myFunc creates a property cache, accessible as usual via myFunc.cache. The cache property is an object (a hash) where the parameter param passed to the function is used as a key and the result of the computation is the value. The result can be any complicated data structure you might need:var myFunc = function (param) { if (!myFunc.cache[param]) { var result = {}; // ... expensive operation ... myFunc.cache[param] = result; } return myFunc.cache[param]; }; // cache storage myFunc.cache = {};
The preceding code assumes that the function takes only one argument param and it’s a primitive data type (such as a string). If you have more parameters and more complex ones, a generic solution would be to serialize them. For example, you can serialize the arguments object as a JSON string and use that string as a key in your cache object:var myFunc = function () { var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)), result; if (!myFunc.cache[cachekey]) { result = {}; // ... expensive operation ... myFunc.cache[cachekey] = result; } return myFunc.cache[cachekey]; }; // cache storage myFunc.cache = {};
Be aware that in serialization, the “identify” of the objects is lost. If you have two different objects that happen to have the same properties, both will share the same cache entry.
Another way to write the previous function is to use arguments.callee to refer to the function instead of hardcoding the function name. Although this is currently possible, be aware that arguments.callee is not allowed in ECMAScript 5 strict mode:var myFunc = function (param) { var f = arguments.callee, result; if (!f.cache[param]) { result = {}; // ... expensive operation ... f.cache[param] = result; } return f.cache[param]; }; // cache storage myFunc.cache = {};
- Configuration Objects
The configuration object pattern is a way to provide cleaner APIs, especially if you’re building a library or any other code that will be consumed by other programs. It’s a fact of life that software requirements change as the software is developed and maintained. It often happens that you start working with some requirements in mind, but more functionality gets added afterward. Imagine you’re writing a function called addPerson(), which accepts a first and last name and adds a person to a list:function addPerson(first, last) {...}
Later you learn that actually the date of birth needs to be stored, too, and optionally the gender and the address. So you modify the function adding the new parameters (carefully putting the optional parameters at the end of the list):function addPerson(first, last, dob, gender, address) {...}
At this point the signature of this function is already getting a little longer. And then you learn you need to add a username and it’s absolutely required, not optional. Now the caller of the function will have to pass even the optional parameters and be careful not to mix the order of the parameters:addPerson("Bruce", "Wayne", new Date(), null, null, "batman");
Passing a large number of parameters is not convenient. A better approach is to substitute all the parameters with only one and make it an object; let’s call it conf, for “configuration”:addPerson(conf); //Then the user of the function can do: var conf = { username: "batman", first: "Bruce", last: "Wayne" }; addPerson(conf);
The pros of the configuration objects are:• No need to remember the parameters and their order • You can safely skip optional parameters • Easier to read and maintain • Easier to add and remove parameters
The cons of the configuration objects are:• You need to remember the names of the parameters • Property names cannot be minified
This pattern could be useful when your function creates DOM elements, for example,or in setting the CSS styles of an element, because elements and styles can have a great number of mostly optional attributes and properties.
发表评论
-
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-15 18:19 11884.Function Pattern Namespace ... -
JavaScript Patterns 读书笔记(二)
2011-02-14 21:20 1166二.Object Object Constructor C ... -
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题解等...
项目介绍小路描述CSS CSS世界练习代码UIAndAnamited 画布,SVG,三等练习代码算法算法练习成分组件封装练习源代码原始解析笔记数据结构斑点结构DesignPatterns |设计模式演示自己实现的一些好玩的小演示
除了每日一题的学习笔记之外还有一些做项目时的记录以及遇到的坑等,对于技术相关的文章基本都是参考众多文章归纳整理学习而写的,文章包括了HTML基础、CSS基础、JavaScript基础与拓展、Browser浏览器相关、Vue使用...
女性笔记 :clapping_hands:欢迎star,也不容易搞丢链接哦! :clapping_hands: 欢迎加入明星,失去联系并不容易!它是什么?我是在参加2020年秋招的时候,实际上那时候往前2个月我才开始系统接触前沿领域。为了快速...
单页图书项目使用项目的IT笔记(Java,Linux,密码学,云,体系结构等)的超级备忘单。克隆并执行下一行以启动本地Web服务器。 $ ./httpServer.py仅需要服务器,以避免浏览器禁用从文件系统路径加载脚本的麻烦。 ...