Процесс объединения одинаковых строк называется « interning » и уже много лет выполняется множеством компиляторов языка, но не всегда. Ответ на этот вопрос, особенно в том виде, в котором он расширился: Геннадий Ванин - Новосибирск, зависит от языка и реализации компилятора. Для Java все константные строки интернированы, как того требует спецификация языка Java . Но это только постоянные строковые выражения, и только тогда, когда они скомпилированы в одно и то же время. Если у вас есть две строки Java, достаточно разделенные во времени и пространстве (, например, , скомпилированные в отдельные файлы JAR), они не будут тем же самым объектом. Аналогично, динамически созданные строки Java (, например , вывод различных методов toString()
) не будут интернированы, если метод специально не запрашивает его через String.intern()
. И да, все используемые интернированные строки будут разделять одни и те же ячейки памяти - это большая часть того, почему строки интернированы в первую очередь.
Что касается других языков, это более важный вопрос, но со всеми информация в этих ответах, я уверен, что вы можете исследовать ее в Интернете. Достаточно сказать, что нет универсального соглашения о том, как это должно быть сделано.
Как я уже говорил в комментариях, прослушивание popstate
и использование метода хэштега (#
) - это самый простой способ сделать маршрутизацию в JS.
Это самый простой способ для маршрутизатора:
//App area
var appArea = document.body.appendChild(document.createElement("div"));
//Registered routes
var routes = [
{
url: '', callback: function () {
appArea.innerHTML = "<h1>Home</h1><a href=\"#todo\">To-Do</a><br/><a href=\"#calendar\">Calendar</a>";
}
}
];
//Routing function
function Routing() {
var hash = window.location.hash.substr(1).replace(/\//ig, '/');
//Default route is first registered route
var route = routes[0];
//Find matching route
for (var index = 0; index < routes.length; index++) {
var testRoute = routes[index];
if (hash == testRoute.url) {
route = testRoute;
}
}
//Fire route
route.callback();
}
//Listener
window.addEventListener('popstate', Routing);
//Initial call
setTimeout(Routing, 0);
//Add other routes
routes.push({ url: "todo", callback: function () { appArea.innerHTML = "<h1>To-Do</h1><a href=\"#\">Home</a><br/><a href=\"#calendar\">Calendar</a>"; } });
routes.push({ url: "calendar", callback: function () { appArea.innerHTML = "<h1>Calendar</h1><a href=\"#\">Home</a></br><a href=\"#todo\">To-Do</a>"; } });
Теперь в любом реальном контексте вам понадобится многократно используемый DOM элементы и функции scope-unload, поэтому вот как это должно выглядеть выше:
// ## Class ## //
var Router = /** @class */ (function () {
function Router() {
}
//Initializer function. Call this to change listening for window changes.
Router.init = function () {
//Remove previous event listener if set
if (this.listener !== null) {
window.removeEventListener('popstate', this.listener);
this.listener = null;
}
//Set new listener for "popstate"
this.listener = window.addEventListener('popstate', function () {
//Callback to Route checker on window state change
this.checkRoute.call(this);
}.bind(this));
//Call initial routing as soon as thread is available
setTimeout(function () {
this.checkRoute.call(this);
}.bind(this), 0);
return this;
};
//Adding a route to the list
Router.addRoute = function (name, url, cb) {
var route = this.routes.find(function (r) { return r.name === name; });
url = url.replace(/\//ig, '/');
if (route === void 0) {
this.routes.push({
callback: cb,
name: name.toString().toLowerCase(),
url: url
});
}
else {
route.callback = cb;
route.url = url;
}
return this;
};
//Adding multiple routes to list
Router.addRoutes = function (routes) {
var _this = this;
if (routes === void 0) { routes = []; }
routes
.forEach(function (route) {
_this.addRoute(route.name, route.url, route.callback);
});
return this;
};
//Removing a route from the list by route name
Router.removeRoute = function (name) {
name = name.toString().toLowerCase();
this.routes = this.routes
.filter(function (route) {
return route.name != name;
});
return this;
};
//Check which route to activate
Router.checkRoute = function () {
//Get hash
var hash = window.location.hash.substr(1).replace(/\//ig, '/');
//Default to first registered route. This should probably be your 404 page.
var route = this.routes[0];
//Check each route
for (var routeIndex = 0; routeIndex < this.routes.length; routeIndex++) {
var routeToTest = this.routes[routeIndex];
if (routeToTest.url == hash) {
route = routeToTest;
break;
}
}
//Run all destroy tasks
this.scopeDestroyTasks
.forEach(function (task) {
task();
});
//Reset destroy task list
this.scopeDestroyTasks = [];
//Fire route callback
route.callback.call(window);
};
//Register scope destroy tasks
Router.onScopeDestroy = function (cb) {
this.scopeDestroyTasks.push(cb);
return this;
};
//Tasks to perform when view changes
Router.scopeDestroyTasks = [];
//Registered Routes
Router.routes = [];
//Listener handle for window events
Router.listener = null;
Router.scopeDestroyTaskID = 0;
return Router;
}());
// ## Implementation ## //
//Router area
var appArea = document.body.appendChild(document.createElement("div"));
//Start router when content is loaded
document.addEventListener("DOMContentLoaded", function () {
Router.init();
});
//Add dashboard route
Router.addRoute("dashboard", "", (function dashboardController() {
//Scope specific elements
var header = document.createElement("h1");
header.textContent = "Dashboard";
//Return initializer function
return function initialize() {
//Apply route
appArea.appendChild(header);
//Destroy elements on exit
Router.onScopeDestroy(dashboardExitController);
};
//Unloading function
function dashboardExitController() {
appArea.removeChild(header);
}
})());
//Add dashboard route
Router.addRoute("dashboard", "", (function dashboardController() {
//Scope specific elements
var header = document.createElement("h1");
header.textContent = "Dashboard";
var links = document.createElement("ol");
links.innerHTML = "<li><a href=\"#todo\">To-Do</a></li><li><a href=\"#calendar\">Calendar</a></li>";
//Return initializer function
return function initialize() {
//Apply route
appArea.appendChild(header);
appArea.appendChild(links);
//Destroy elements on exit
Router.onScopeDestroy(dashboardExitController);
};
//Unloading function
function dashboardExitController() {
appArea.removeChild(header);
appArea.removeChild(links);
}
})());
//Add other routes
Router.addRoutes([
{
name: "todo",
url: "todo",
callback: (function todoController() {
//Scope specific elements
var header = document.createElement("h1");
header.textContent = "To-do";
var links = document.createElement("ol");
links.innerHTML = "<li><a href=\"#\">Dashboard</a></li><li><a href=\"#calendar\">Calendar</a></li>";
//Return initializer function
return function initialize() {
//Apply route
appArea.appendChild(header);
appArea.appendChild(links);
//Destroy elements on exit
Router.onScopeDestroy(todoExitController);
};
//Unloading function
function todoExitController() {
appArea.removeChild(header);
appArea.removeChild(links);
}
})()
},
{
name: "calendar",
url: "calendar",
callback: (function calendarController() {
//Scope specific elements
var header = document.createElement("h1");
header.textContent = "Calendar";
var links = document.createElement("ol");
links.innerHTML = "<li><a href=\"#\">Dashboard</a></li><li><a href=\"#todo\">To-Do</a></li>";
//Return initializer function
return function initialize() {
//Apply route
appArea.appendChild(header);
appArea.appendChild(links);
//Destroy elements on exit
Router.onScopeDestroy(calendarExitController);
};
//Unloading function
function calendarExitController() {
appArea.removeChild(header);
appArea.removeChild(links);
}
})()
}
]);