Is '$' already defined in Chrome?
If you enter $ in the Chrome console on a simple html page without a script. You will see this conclusion
> $ < bound(selector, startNode) However, when you make a window. $, undefined output,
> window.$ < undefined What defines $ here, and why can't I access it through the window object?
$ is a local variable entered into your console from the __commandLineAPI object via the with statement that wraps your code (which is why this is not a global variable). If you check it more closely (using, for example, debugger; $('*'); ), you will also see that this is basically a function attached to the current window with the following source:
$: function (selector, opt_startNode) { if (this._canQuerySelectorOnNode(opt_startNode)) return opt_startNode.querySelector(selector); return inspectedWindow.document.querySelector(selector); } (defined on CommandLineAPIImpl.prototype )
From the Command Line API Reference :
The command line API is a set of functions for performing common tasks using the Chrome Developer Tools. These include convenient functions for selecting and checking items in the DOM ...
$ (selector) Returns a reference to the first DOM element with the specified CSS selector. This function is an alias for the document.querySelector () function.
For example:
$('body') Adding to the previous answers, it can be found in the VM chrome code.
// NOTE: Please keep the list of API methods below snchronized to that in WebInspector.RuntimeModel! // NOTE: Argument names of these methods will be printed in the console, so use pretty names! /** * @type {!Array.<string>} * @const */ CommandLineAPI.members_ = [ "$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "getEventListeners", "debug", "undebug", "monitor", "unmonitor", "table" ]; All implementations can be found here.
CommandLineAPIImpl.prototype = { /** * @param {string} selector * @param {!Node=} opt_startNode * @return {*} */ $: function (selector, opt_startNode) { if (this._canQuerySelectorOnNode(opt_startNode)) return opt_startNode.querySelector(selector); return inspectedWindow.document.querySelector(selector); }, /** * @param {string} selector * @param {!Node=} opt_startNode * @return {*} */ $$: function (selector, opt_startNode) { if (this._canQuerySelectorOnNode(opt_startNode)) return opt_startNode.querySelectorAll(selector); return inspectedWindow.document.querySelectorAll(selector); }, /** * @param {!Node=} node * @return {boolean} */ _canQuerySelectorOnNode: function(node) { return !!node && InjectedScriptHost.subtype(node) === "node" && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE); }, /** * @param {string} xpath * @param {!Node=} opt_startNode * @return {*} */ $x: function(xpath, opt_startNode) { var doc = (opt_startNode && opt_startNode.ownerDocument) || inspectedWindow.document; var result = doc.evaluate(xpath, opt_startNode || doc, null, XPathResult.ANY_TYPE, null); switch (result.resultType) { case XPathResult.NUMBER_TYPE: return result.numberValue; case XPathResult.STRING_TYPE: return result.stringValue; case XPathResult.BOOLEAN_TYPE: return result.booleanValue; default: var nodes = []; var node; while (node = result.iterateNext()) push(nodes, node); return nodes; } }, /** * @return {*} */ dir: function(var_args) { return InjectedScriptHost.callFunction(inspectedWindow.console.dir, inspectedWindow.console, slice(arguments)); }, /** * @return {*} */ dirxml: function(var_args) { return InjectedScriptHost.callFunction(inspectedWindow.console.dirxml, inspectedWindow.console, slice(arguments)); }, /** * @return {!Array.<string>} */ keys: function(object) { return Object.keys(object); }, /** * @return {!Array.<*>} */ values: function(object) { var result = []; for (var key in object) push(result, object[key]); return result; }, /** * @return {*} */ profile: function(opt_title) { return InjectedScriptHost.callFunction(inspectedWindow.console.profile, inspectedWindow.console, slice(arguments)); }, /** * @return {*} */ profileEnd: function(opt_title) { return InjectedScriptHost.callFunction(inspectedWindow.console.profileEnd, inspectedWindow.console, slice(arguments)); }, /** * @param {!Object} object * @param {!Array.<string>|string=} opt_types */ monitorEvents: function(object, opt_types) { if (!object || !object.addEventListener || !object.removeEventListener) return; var types = this._normalizeEventTypes(opt_types); for (var i = 0; i < types.length; ++i) { object.removeEventListener(types[i], this._logEvent, false); object.addEventListener(types[i], this._logEvent, false); } }, /** * @param {!Object} object * @param {!Array.<string>|string=} opt_types */ unmonitorEvents: function(object, opt_types) { if (!object || !object.addEventListener || !object.removeEventListener) return; var types = this._normalizeEventTypes(opt_types); for (var i = 0; i < types.length; ++i) object.removeEventListener(types[i], this._logEvent, false); }, /** * @param {*} object * @return {*} */ inspect: function(object) { return injectedScript._inspect(object); }, copy: function(object) { var string; if (injectedScript._subtype(object) === "node") { string = object.outerHTML; } else if (injectedScript.isPrimitiveValue(object)) { string = toString(object); } else { try { string = JSON.stringify(object, null, " "); } catch (e) { string = toString(object); } } var hints = { copyToClipboard: true, __proto__: null }; var remoteObject = injectedScript._wrapObject(string, "") InjectedScriptHost.inspect(remoteObject, hints); }, clear: function() { InjectedScriptHost.clearConsoleMessages(); }, /** * @param {!Node} node * @return {!Array.<!{type: string, listener: function(), useCapture: boolean, remove: function()}>|undefined} */ getEventListeners: function(node) { var result = nullifyObjectProto(InjectedScriptHost.getEventListeners(node)); if (!result) return result; /** @this {{type: string, listener: function(), useCapture: boolean}} */ var removeFunc = function() { node.removeEventListener(this.type, this.listener, this.useCapture); } for (var type in result) { var listeners = result[type]; for (var i = 0, listener; listener = listeners[i]; ++i) { listener["type"] = type; listener["remove"] = removeFunc; } } return result; }, debug: function(fn) { InjectedScriptHost.debugFunction(fn); }, undebug: function(fn) { InjectedScriptHost.undebugFunction(fn); }, monitor: function(fn) { InjectedScriptHost.monitorFunction(fn); }, unmonitor: function(fn) { InjectedScriptHost.unmonitorFunction(fn); }, table: function(data, opt_columns) { InjectedScriptHost.callFunction(inspectedWindow.console.table, inspectedWindow.console, slice(arguments)); }, /** * @param {number} num */ _inspectedObject: function(num) { return InjectedScriptHost.inspectedObject(num); }, /** * @param {!Array.<string>|string=} types * @return {!Array.<string>} */ _normalizeEventTypes: function(types) { if (typeof types === "undefined") types = ["mouse", "key", "touch", "control", "load", "unload", "abort", "error", "select", "input", "change", "submit", "reset", "focus", "blur", "resize", "scroll", "search", "devicemotion", "deviceorientation"]; else if (typeof types === "string") types = [types]; var result = []; for (var i = 0; i < types.length; ++i) { if (types[i] === "mouse") push(result, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout", "mousewheel"); else if (types[i] === "key") push(result, "keydown", "keyup", "keypress", "textInput"); else if (types[i] === "touch") push(result, "touchstart", "touchmove", "touchend", "touchcancel"); else if (types[i] === "control") push(result, "resize", "scroll", "zoom", "focus", "blur", "select", "input", "change", "submit", "reset"); else push(result, types[i]); } return result; }, /** * @param {!Event} event */ _logEvent: function(event) { inspectedWindow.console.log(event.type, event); } } To verify this, simply click bound(selector, startNode) its active link
This is a console built-in function only:

