Home Web Front-end JS Tutorial seajs1.3.0 source code analysis module dependency orderly loading_javascript skills

seajs1.3.0 source code analysis module dependency orderly loading_javascript skills

May 16, 2016 pm 05:48 PM
load Source code parse

This is the core part of seajs loader. Some IE compatible parts are not very clear yet. The main thing is to understand how each module relies on orderly loading and the CMD specification.

The code is a bit long, so you need to read it patiently:

Copy the code The code is as follows:

/**
* The core of loader
*/
;(function(seajs, util, config) {
//Module cache
var cachedModules = {}
//Interface modification Cache
var cachedModifiers = {}
// Compile Queue
var compileStack = []
// Module Status
var STATUS = {
'FETCHING': 1, // The module file is fetching now. The module is being downloaded
'FETCHED': 2, // The module file has been fetched. The module has been downloaded
'SAVED': 3, // The module info has been saved. Module Information has been saved
'READY': 4, // All dependencies and self are ready to compile. The module's dependencies have been downloaded and are waiting to be compiled
'COMPILING': 5, // The module is in compiling now . The module is being compiled
'COMPILED': 6 // The module is compiled and module.exports is available. The module is compiled
}


function Module(uri, status) {
this.uri = uri
this.status = status || 0

// this.id is set when saving
// this.dependencies is set when saving
/ / this.factory is set when saving
// this.exports is set when compiling
// this.parent is set when compiling
// this.require is set when compiling
}


Module.prototype._use = function(ids, callback) {
//Convert to array, unified operation
util.isString(ids) && (ids = [ids])
// Use the path resolution mechanism inside the module system to resolve and return the module path
var uris = resolve(ids, this.uri)

this._load(uris, function() {
// Loads preload files introduced in modules before compiling.
// Before compilation, call preload again to preload the module
// Because seajs.config can be called at any time to configure the preload module during code execution
preload(function() {
// Compile each module and pass the exports of each module as parameters to the callback function
var args = util.map(uris, function(uri) {
return uri ? cachedModules[uri]._compile() : null
})

if (callback) {
// null makes this pointer in the callback function window
callback.apply(null, args)
}
})
})
}

// The main module loads dependent modules (called submodules) and executes the callback function
Module. prototype._load = function(uris, callback) {
// Filter the uris array
// Case 1: The module does not exist in the cache, return its uri
// Case 2: The module exists in the cache , but its status < STATUS.READY (i.e. not ready to compile)
var unLoadedUris = util.filter(uris, function(uri) {
return uri && (!cachedModules[uri] ||
cachedModules[uri].status < STATUS.READY)
})

var length = unLoadedUris.length
// If length is 0, it means that the dependencies are 0 or have been downloaded , then perform the callback compilation operation
if (length === 0) {
callback()
return
}

var remain = length

for ( var i = 0; i < length; i ) {
// Closure, providing context for the onFetched function
(function(uri) {
// Create module object
var module = cachedModules[uri] ||
(cachedModules[uri] = new Module(uri, STATUS.FETCHING))
//If the module has been downloaded, then execute onFetched, otherwise execute the fetch operation (request module)
module.status >= STATUS.FETCHED ? onFetched() : fetch(uri, onFetched)

function onFetched() {
// cachedModules[uri] is changed in un-correspondence case
module = cachedModules[uri]
// If the module status is SAVED, it means that the module’s dependencies have been determined, then download the dependent module
if (module.status >= STATUS.SAVED) {
// Get the list of dependent modules from the module information and process circular dependencies
var deps = getPureDependencies(module)
// If dependencies exist, continue downloading
if (deps.length) {
Module.prototype._load(deps, function() {
cb(module)
})
}
// Otherwise, execute cb directly
else {
cb(module)
}
}
// Maybe failed to fetch successfully, such as 404 or non-module.
// In these cases, just call cb function directly.
// If the download module does not Success, such as 404 or module irregularity (code error), the module status may be fetching or fetched
// At this time, the callback function is directly executed. When compiling the module, the module will only return null
else {
cb()
}
}

})(unLoadedUris[i])
}

function cb(module) {
// Change the module status to READY. When remain is 0, it means that the module dependencies have been downloaded, then execute callback
(module || {}).status < STATUS.READY && (module.status = STATUS.READY )
--remain === 0 && callback()
}
}


Module.prototype._compile = function() {
var module = this
// If the module has been compiled, directly return module.exports
if (module.status === STATUS.COMPILED) {
return module.exports
}

// Just return null when:
// 1. the module file is 404.
// 2. the module file is not written with valid module format.
// 3 . other error cases.
// This is to handle some exceptions. In this case, null is returned directly
if (module.status < STATUS.SAVED && !hasModifiers(module)) {
return null
}
// Change the module status to COMPILING, indicating that the module is compiling
module.status = STATUS.COMPILING

// Used internally by the module, it is a method used to obtain the information provided by other modules ( Called submodule) interface, synchronous operation
function require(id) {
// Resolve the module path according to id
var uri = resolve(id, module.uri)
// Get the module from the module cache (note that the submodule here has actually been downloaded as a dependency of the main module)
var child = cachedModules[uri]

// Just return null when uri is invalid.
// If child is empty, it can only mean that the parameter filling is incorrect and the uri is incorrect, then null is returned directly
if (!child) {
return null
}

// Avoids circular calls.
// If the status of the submodule is STATUS.COMPILING, return child.exports directly to avoid repeatedly compiling the module due to circular dependencies
if (child.status === STATUS.COMPILING) {
return child.exports
}
// Points to the module that calls the current module during initialization. According to this attribute, you can get the Call Stack when the module is initialized.
child.parent = module
// Return the compiled child’s module.exports
return child._compile()
}
// Used internally by the module to load the module asynchronously and execute the specified callback after the loading is completed.
require.async = function(ids, callback) {
module._use(ids, callback)
}
// Use the path resolution mechanism inside the module system to parse and return the module path. This function does not load the module and only returns the resolved absolute path.
require.resolve = function(id) {
return resolve(id, module.uri)
}
// Through this attribute, you can view all modules loaded by the module system.
// In some cases, if you need to reload a module, you can get the uri of the module, and then delete its information by delete require.cache[uri]. This will be obtained again the next time you use it.
require.cache = cachedModules

// require is a method used to obtain the interfaces provided by other modules.
module.require = require
// exports is an object used to provide module interfaces to the outside world.
module.exports = {}
var factory = module.factory

// When factory is a function, it represents the construction method of the module. By executing this method, you can get the interface provided by the module.
if (util.isFunction(factory)) {
compileStack.push(module)
runInModuleContext(factory, module)
compileStack.pop()
}
// factory is When the object, string and other non-function types are used, the interface of the module is the object, string and other values.
// For example: define({ "foo": "bar" });
// For example: define('I am a template. My name is {{name}}.');
else if (factory !== undefined) {
module.exports = factory
}

// Change the module status to COMPILED, indicating that the module has been compiled
module.status = STATUS.COMPILED
// Execute module interface modification through seajs.modify()
execModifiers(module)
return module.exports
}


Module._define = function(id , deps, factory) {
var argsLength = arguments.length
// Perform parameter matching according to the number of parameters passed in

// define(factory)
// One parameter Case:
// id: undefined
// deps: undefined (the list of dependent modules will be taken out later according to regular rules)
// factory: function
if (argsLength === 1) {
factory = id
id = undefined
}
// define(id || deps, factory)
// case of two parameters:

else if (argsLength === 2) {
// Default: define(id, factory)
// id : '...'
// deps : undefined
// factory : function
factory = deps
deps = undefined

// define(deps, factory)
// If the first parameter is an array: define(deps, factory)
// id : undefined
// deps : [...]
// factory : function
if (util.isArray(id)) {
deps = id
id = undefined
}
}

// Parses dependencies.
// If deps is not an array (that is, deps does not specify a value), then parse the dependencies through regular expressions
if (!util.isArray( deps) && util.isFunction(factory)) {
deps = util.parseDependencies(factory.toString())
}

// Meta information, which will then be passed to the corresponding module
var meta = { id: id, dependencies: deps, factory: factory } in the object
var derivedUri

// Try to derive uri in IE6-9 for anonymous modules.
/ / For IE6-9, try to get the uri of the module through interactive script
if (document.attachEvent) {
// Try to get the current script.
// Get the current script
var script = util.getCurrentScript()
if (script) {
// UnpareseMap the url of the current script to keep it consistent with the key in the module cache
derivedUri = util.unParseMap(util.getScriptAbsoluteSrc(script) )
}

if (!derivedUri) {
util.log('Failed to derive URI from interactive script for:',
factory.toString(), 'warn')

// NOTE: If the id-deriving methods above is failed, then falls back
// to use onload event to get the uri.
}
}

// Gets uri directly for specific module.
// If the id is given, then the path is parsed according to the id
// Obviously if the id is not specified:
// For non-IE browsers, return undefined (derivedUri is empty)
// For IE browser, the src of CurrentScript is returned
// If id is specified:
// The path url parsed by seajs is returned
var resolvedUri = id ? resolve(id) : derivedUri
// If uri exists, store module information
if (resolvedUri) {
// For IE:
// If the first module in a package is not the cachedModules[derivedUri]
// self, it should assign to the correct module when found.
if (resolvedUri === derivedUri) {
var refModule = cachedModules[derivedUri]
if (refModule && refModule.realUri &&
refModule.status === STATUS.SAVED) {
cachedModules[derivedUri] = null
}
}
//Storage module information
var module = save(resolvedUri, meta)

// For IE:
// Assigns the first module in package to cachedModules[derivedUrl]
if (derivedUri) {
/ / cachedModules[derivedUri] may be undefined in combo case.
if ((cachedModules[derivedUri] || {}).status === STATUS.FETCHING) {
cachedModules[derivedUri] = module
module .realUri = derivedUri
}
}
else {
// Store the first module into firstModuleInPackage
firstModuleInPackage || (firstModuleInPackage = module)
}
}
// When uri does not exist, module information is stored in the onload callback, where there is a closure
else {
// Saves information for "memoizing" work in the onload event.
/ / Because the uri at this time is not known, the meta information is temporarily stored in anonymousModuleMeta, and the module save operation is performed in the onload callback
anonymousModuleMeta = meta
}

}

// Get the module being compiled
Module._getCompilingModule = function() {
return compileStack[compileStack.length - 1]
}

// Quickly view the sum from seajs.cache Get the loaded module interface, the return value is the module.exports array
// selector supports strings and regular expressions
Module._find = function(selector) {
var matches = []

util.forEach(util.keys(cachedModules), function(uri) {
if (util.isString(selector) && uri.indexOf(selector) > -1 ||
util.isRegExp( selector) && selector.test(uri)) {
var module = cachedModules[uri]
module.exports && matches.push(module.exports)
}
})

return matches
}

// Modify module interface
Module._modify = function(id, modifier) ​​{
var uri = resolve(id)
var module = cachedModules[uri]
// If the module exists and is in the COMPILED state, then perform the interface modification operation
if (module && module.status === STATUS.COMPILED) {
runInModuleContext(modifier, module)
}
// Otherwise, put it into the modified interface cache
else {
cachedModifiers[uri] || (cachedModifiers[uri] = [])
cachedModifiers[uri].push(modifier) ​​
}

return seajs
}


// For plugin developers
Module.STATUS = STATUS
Module._resolve = util.id2Uri
Module._fetch = util.fetch
Module.cache = cachedModules


// Helpers
// -------
// List of modules being downloaded
var fetchingList = {}
//Downloaded module list
var fetchedList = {}
// Callback function list
var callbackList = {}
//Anonymous module meta information
var anonymousModuleMeta = null
var firstModuleInPackage = null
// Circular dependency stack
var circularCheckStack = []

// Path to batch parsed modules
function resolve(ids, refUri) {
if (util.isString(ids)) {
return Module._resolve(ids, refUri)
}

return util.map(ids, function(id) {
return resolve( id, refUri)
})
}

function fetch(uri, callback) {
// When fetching, first convert the uri according to map rules
var requestUri = util. parseMap(uri)
// Search in fethedList (downloaded module list), if any, return directly and execute the callback function
// TODO: Why might this module exist in fetchedList in this step?
if (fetchedList[requestUri]) {
// See test/issues/debug-using-map
cachedModules[uri] = cachedModules[requestUri]
callback()
return
}
// Search in the fetchingList (the list of modules being downloaded). If there is any, just add the callback function to the list and return directly
if (fetchingList[requestUri]) {
callbackList[requestUri].push(callback)
return
}
// If you get to this step, it means that the module is requested for the first time,
// Then insert the module in fetchingList information, indicating that the module is already in the download list, and initializes the callback function list corresponding to the module
fetchingList[requestUri] = true
callbackList[requestUri] = [callback]

// Fetches it
// Get the module, that is, initiate a request
Module._fetch(
requestUri,

function() {
// Insert the module’s information in fetchedList to represent the The module has been downloaded
fetchedList[requestUri] = true

// Updates module status
var module = cachedModules[uri]
// At this time the status may be STATUS.SAVED, previously in It has been said in _define
if (module.status === STATUS.FETCHING) {
module.status = STATUS.FETCHED
}

// Saves anonymous module meta data
// Because it is an anonymous module (the uri is obtained through the closure at this time, and the module information is stored here)
// And set anonymousModuleMeta to empty
if (anonymousModuleMeta) {
save(uri, anonymousModuleMeta)
anonymousModuleMeta = null
}

// Assigns the first module in package to cachedModules[uri]
// See: test/issues/un-correspondence
if ( firstModuleInPackage && module.status === STATUS.FETCHED) {
cachedModules[uri] = firstModuleInPackage
firstModuleInPackage.realUri = uri
}
firstModuleInPackage = null

// Clears
// Clear module information in fetchingList because the module has been fetched and saved
if (fetchingList[requestUri]) {
delete fetchingList[requestUri]
}

// Calls callbackList
// Call the callback functions in sequence and clear the callback function list
if (callbackList[requestUri]) {
util.forEach(callbackList[requestUri], function(fn) {
fn()
})
delete callbackList[requestUri]
}

},

config.charset
)
}

function save( uri, meta) {
var module = cachedModules[uri] || (cachedModules[uri] = new Module(uri))

// Don't override already saved module
// this The status may have two states:
// STATUS.FETCHING, called in define (id specified), stores module information
// STATUS.FETCHED, called in the onload callback function, stores module information
if (module.status < STATUS.SAVED) {
// Lets anonymous module id equal to its uri
// Anonymous module (that is, no id is specified), use its uri as id
module.id = meta.id || uri
// Parse the absolute path from the dependency (array) and store it in the module information
module.dependencies = resolve(
util.filter(meta .dependencies || [], function(dep) {
return !!dep
}), uri)
// Store factory (module code to be executed, which may also be an object or string, etc.)
module.factory = meta.factory

// Updates module status
// The update module status is SAVED, (note that it only has dependencies at this time, not all have been downloaded yet (i.e. Not READY yet))
module.status = STATUS.SAVED
}

return module
}

// Execute module code according to module context
function runInModuleContext (fn, module) {
// Pass in two parameters related to the module and the module itself
// exports is used to expose the interface
// require is used to obtain dependent modules (synchronization) (compilation)
var ret = fn(module.require, module.exports, module)
// Supports return value exposure interface form, such as:
// return {
// fn1 : xx
// ,fn2 : xx
// ...
// }
if (ret !== undefined) {
module.exports = ret
}
}
// Determine whether the module has interface modifications
function hasModifiers(module) {
return !!cachedModifiers[module.realUri || module.uri]
}
// Modify the module interface
function execModifiers(module) {
var uri = module.realUri || module.uri
var modifiers = cachedModifiers[uri]
// The internal variable cachedModifiers is used to store the values ​​defined by the user through the seajs.modify method Modification point
//Check whether the uri has been changed by modify
if (modifiers) {
// Execute factory uniformly on the modification point and return the modified module.exports
util.forEach( modifiers, function(modifier) ​​{
runInModuleContext(modifier, module)
})
// Delete the modification points defined by the modify method to avoid executing it again
delete cachedModifiers[uri]
}
}

//Get pure dependencies and get a dependency array without circular dependencies
function getPureDependencies(module) {
var uri = module.uri
// For each dependency Filter the items, eliminate those that may form circular dependencies, and print out a warning log
return util.filter(module.dependencies, function(dep) {
// First put the uri of the checked module into In the circular dependency check stack, subsequent checks will use
circularCheckStack = [uri]
//Next, check whether the module uri has a circular dependency on its dependent modules
var isCircular = isCircularWaiting(cachedModules[dep ])
if (isCircular) {
// If it is circular, put the uri into the circular dependency check stack
circularCheckStack.push(uri)
// Print out the circular warning log
printCircularLog(circularCheckStack)
}

return !isCircular
})
}

function isCircularWaiting(module) {
// If the dependent module does not exist, then Return false, because the dependencies of the dependent module cannot be obtained at this time, so no judgment can be made here
// Or if the status value of the module is equal to saved, false is also returned, because when the module status is saved, it represents the information of the module. Already have it,
// So even though a circular dependency is formed, when the main module is required, it can be compiled normally and the main module interface is returned (it seems that nodejs will return undefined)
if (!module || module.status !== STATUS.SAVED) {
return false
}
// If it is not the above situation, then put the uri of the dependent module into the circular dependency check stack, and subsequent checks will use
circularCheckStack.push(module.uri)
// Get the dependent module of the dependent module again
var deps = module.dependencies

if (deps.length) {
// Through loop Dependency check stack, check whether there is a circular dependency (here is the first layer of dependency module check, circular dependency with the main module)
if (isOverlap(deps, circularCheckStack)) {
return true
}
// If the above situation does not exist, then further check the dependent modules of the dependent modules to see if they have a circular dependency on the module of the uri in the circular dependency check stack
// In this case, it is recursive and circular The dependency check stack is like a chain. The current module checks the main module, the main module of the main module... until the main module at the top to determine whether there are dependencies
for (var i = 0; i < deps.length; i ) {
if (isCircularWaiting(cachedModules[deps[i]])) {
return true
}
}
}
// if not If there is a circular dependency, then pop out the module uri that has been pushed in before and return false
circularCheckStack.pop()
return false
}
// Print out the circular warning log
function printCircularLog (stack, type) {
util.log('Found circular dependencies:', stack.join(' --> '), type)
}
//Determine whether two arrays are duplicated The value of
function isOverlap(arrA, arrB) {
var arrC = arrA.concat(arrB)
return arrC.length > util.unique(arrC).length
}
/ / Read from the configuration file whether there are modules that need to be loaded in advance
// If there is a preloaded module, first set the preloaded module to empty (to ensure that it does not have to be loaded again next time), and load the preloaded module and execute the callback, if If not, execute sequentially
function preload(callback) {
var preloadMods = config.preload.slice()
config.preload = []
preloadMods.length ? globalModule._use(preloadMods, callback) : callback()
}


// Public API
// API exposed to the outside world
// ----------
// The global module can be considered as the page module. The js and css files in the page are loaded through it
// The initial state of the module is COMPILED, and the uri is the uri of the page
var globalModule = new Module(util .pageUri, STATUS.COMPILED)

// Page js, css file loader
seajs.use = function(ids, callback) {
// Loads preload modules before all other modules.
// Preload module
preload(function() {
globalModule._use(ids, callback)
})

// Chain
return seajs
}


// For normal users
// For normal users to call
seajs.define = Module._define
seajs.cache = Module.cache
seajs.find = Module._find
seajs.modify = Module._modify


// For plugin developers
// For developers
seajs.pluginSDK = {
Module: Module ,
util: util,
config: config
}

})(seajs, seajs._util, seajs._config)
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

A deep dive into the meaning and usage of HTTP status code 460 A deep dive into the meaning and usage of HTTP status code 460 Feb 18, 2024 pm 08:29 PM

In-depth analysis of the role and application scenarios of HTTP status code 460 HTTP status code is a very important part of web development and is used to indicate the communication status between the client and the server. Among them, HTTP status code 460 is a relatively special status code. This article will deeply analyze its role and application scenarios. Definition of HTTP status code 460 The specific definition of HTTP status code 460 is "ClientClosedRequest", which means that the client closes the request. This status code is mainly used to indicate

iBatis and MyBatis: Comparison and Advantage Analysis iBatis and MyBatis: Comparison and Advantage Analysis Feb 18, 2024 pm 01:53 PM

iBatis and MyBatis: Differences and Advantages Analysis Introduction: In Java development, persistence is a common requirement, and iBatis and MyBatis are two widely used persistence frameworks. While they have many similarities, there are also some key differences and advantages. This article will provide readers with a more comprehensive understanding through a detailed analysis of the features, usage, and sample code of these two frameworks. 1. iBatis features: iBatis is an older persistence framework that uses SQL mapping files.

Error loading plugin in Illustrator [Fixed] Error loading plugin in Illustrator [Fixed] Feb 19, 2024 pm 12:00 PM

When launching Adobe Illustrator, does a message about an error loading the plug-in pop up? Some Illustrator users have encountered this error when opening the application. The message is followed by a list of problematic plugins. This error message indicates that there is a problem with the installed plug-in, but it may also be caused by other reasons such as a damaged Visual C++ DLL file or a damaged preference file. If you encounter this error, we will guide you in this article to fix the problem, so continue reading below. Error loading plug-in in Illustrator If you receive an "Error loading plug-in" error message when trying to launch Adobe Illustrator, you can use the following: As an administrator

Detailed explanation of Oracle error 3114: How to solve it quickly Detailed explanation of Oracle error 3114: How to solve it quickly Mar 08, 2024 pm 02:42 PM

Detailed explanation of Oracle error 3114: How to solve it quickly, specific code examples are needed. During the development and management of Oracle database, we often encounter various errors, among which error 3114 is a relatively common problem. Error 3114 usually indicates a problem with the database connection, which may be caused by network failure, database service stop, or incorrect connection string settings. This article will explain in detail the cause of error 3114 and how to quickly solve this problem, and attach the specific code

Stremio subtitles not working; error loading subtitles Stremio subtitles not working; error loading subtitles Feb 24, 2024 am 09:50 AM

Subtitles not working on Stremio on your Windows PC? Some Stremio users reported that subtitles were not displayed in the videos. Many users reported encountering an error message that said "Error loading subtitles." Here is the full error message that appears with this error: An error occurred while loading subtitles Failed to load subtitles: This could be a problem with the plugin you are using or your network. As the error message says, it could be your internet connection that is causing the error. So please check your network connection and make sure your internet is working properly. Apart from this, there could be other reasons behind this error, including conflicting subtitles add-on, unsupported subtitles for specific video content, and outdated Stremio app. like

Parsing Wormhole NTT: an open framework for any Token Parsing Wormhole NTT: an open framework for any Token Mar 05, 2024 pm 12:46 PM

Wormhole is a leader in blockchain interoperability, focused on creating resilient, future-proof decentralized systems that prioritize ownership, control, and permissionless innovation. The foundation of this vision is a commitment to technical expertise, ethical principles, and community alignment to redefine the interoperability landscape with simplicity, clarity, and a broad suite of multi-chain solutions. With the rise of zero-knowledge proofs, scaling solutions, and feature-rich token standards, blockchains are becoming more powerful and interoperability is becoming increasingly important. In this innovative application environment, novel governance systems and practical capabilities bring unprecedented opportunities to assets across the network. Protocol builders are now grappling with how to operate in this emerging multi-chain

Outlook freezes when inserting hyperlink Outlook freezes when inserting hyperlink Feb 19, 2024 pm 03:00 PM

If you encounter freezing issues when inserting hyperlinks into Outlook, it may be due to unstable network connections, old Outlook versions, interference from antivirus software, or add-in conflicts. These factors may cause Outlook to fail to handle hyperlink operations properly. Fix Outlook freezes when inserting hyperlinks Use the following fixes to fix Outlook freezes when inserting hyperlinks: Check installed add-ins Update Outlook Temporarily disable your antivirus software and then try creating a new user profile Fix Office apps Program Uninstall and reinstall Office Let’s get started. 1] Check the installed add-ins. It may be that an add-in installed in Outlook is causing the problem.

Analysis of the meaning and usage of midpoint in PHP Analysis of the meaning and usage of midpoint in PHP Mar 27, 2024 pm 08:57 PM

[Analysis of the meaning and usage of midpoint in PHP] In PHP, midpoint (.) is a commonly used operator used to connect two strings or properties or methods of objects. In this article, we’ll take a deep dive into the meaning and usage of midpoints in PHP, illustrating them with concrete code examples. 1. Connect string midpoint operator. The most common usage in PHP is to connect two strings. By placing . between two strings, you can splice them together to form a new string. $string1=&qu

See all articles