Home > Web Front-end > JS Tutorial > body text

10 basic questions you must master in JavaScript

coldplay.xixi
Release: 2020-10-13 13:47:27
forward
2009 people have browsed it

10 basic questions you must master in JavaScript

JavaScript is a client-side programming language. Used by more than 90% of websites around the world, it is one of the most commonly used programming languages ​​in the world. Therefore, today’s JavaScript column will discuss 10 common questions about JavaScript.

1. How to remove a specific item from an array

Idea: First, use indexOf to find the index of the array element to be deleted. , and then use the splice method to delete the item corresponding to the index.

splice() is a non-pure function that changes the contents of an array by removing existing elements and/or adding new elements. The second parameter of

const array = [2, 5, 9]

const index = array.indexOf(5)
if (index > -1) {
  array.splice(index, 1)
}

console.log(array)
// [ 2, 9 ]复制代码
Copy after login

splice is the number of elements to be deleted. Note that splice modifies the array where appropriate and returns a new array containing the deleted elements.

Next, we can improve it. There are two functions below, the first function only removes one match (i.e. removes the first match 5 from [2,5,9,1,5,8,5] ), while the second function removes all matches:

// 仅删除第一个匹配项
function removeItemOnce (arr, value) {
  let index = arr.indexOf(value)
  if (index > -1) {
    arr.splice(index, 1)
  }
  return arr
}

// 删除所有匹配项
function removeItemAll (arr, value) {
  let i = 0
  while(i < arr.length) {
    if (arr[i] === value) {
      arr.splice(i, 1)
    } else {
      ++i
    }
  }
}复制代码
Copy after login

Removes the element at index i in the array:

Delete the element at index i from the array:

array.splice(i, 1)复制代码
Copy after login

If you want to delete every element with value number from the array, you can do this:

for (let i = array.length - 1; i>=0; i--) {
  if (array[i] === number) {
    array.splice(i, 1)
  }
}复制代码
Copy after login

If you just want to make the element at index i no longer exist, but don't want to change the index of other elements:

delete array[i]复制代码
Copy after login

2. How to use jQuery or pure JS to make the user Redirecting from one page to another

jQuery is not required, window.location.replace(…)is best suited for simulating HTTP redirects. window.location.replace(...) is preferable to using window.location.href because replace() does not retain the original page in the session history For the record, this means users won't be stuck with a never-ending back button.

If you want to simulate clicking a link, you can use location.href, if you want to simulate an HTTP redirect, use location.replace.

Example:

//模拟HTTP重定向
window.location.replace("http://stackoverflow.com")

// 模拟单击链接
window.location.href = "http://stackoverflow.com"复制代码
Copy after login

You can also do this:

$(location).attr(&#39;href&#39;, &#39;http://stackoverflow.com&#39;)复制代码
Copy after login

3. How JavaScript closures work

Closing A package is a function and a reference to the scope outside that function (the lexical environment), which is part of every execution context (the stack) and is the mapping between identifiers (i.e. local variable names) and values.

Every function in JavaScript maintains a reference to its external lexical environment. This reference is used to configure the execution context created when the function is called. Whenever a function is called, this reference enables code within the function to view variables declared outside the function.

In the following code, inner forms a closure together with the lexical environment of the execution context created when foo is called, and hides the variable ## from the outside #secret:

function foo() {
  const secret = Math.trunc(Math.random()*100)
  return function inner() {
    console.log(`The secret number is ${secret}.`)
  }
}
const f = foo() // secret 不能从foo 外部直接访问
f() // 访问 secret 的唯一办法就是调用 f复制代码
Copy after login

In other words, in JavaScript, functions carry a reference to private state, which only they (and any other functions declared in the same lexical environment) can access state. This state is invisible to function callers, which provides an excellent mechanism for data hiding and encapsulation.

Remember that functions in JavaScript can be passed like variables, which means that these pairs of functions and states can be passed around the program: similar to passing instances of classes in C.

If JavaScript didn't have closures, more state would have to be passed explicitly between functions, making parameter lists longer and code more redundant.

So, if you want a function to always have access to private state, you can use a closure. We often want to associate state with a function. For example, in Java or C, when you add private instance variables and methods to a class, you are associating state with functionality.

In C and most other programming languages, after a function returns, all local variables are no longer accessible because the stack is destroyed. In JavaScript, if you declare a function within another function, the local variables of the outer function remain accessible after returning. This way, in the above code,

secret is still available internally to the function object after returning from foo.

Closures are useful when you need private state associated with a function. This is a very common scenario, JavaScript didn't have a class syntax until 2015, it still didn't have a private field syntax, closures filled this need.

Private instance variables

In the following example, the function

toString hides some details of the Car class.

function Car(manufacturer, model, year, color) {
  return {
    toString() {
      return `${manufacturer} ${model} (${year}, ${color})`
    }
  }
}
const car = new Car(&#39;Aston Martin&#39;,&#39;V8 Vantage&#39;,&#39;2012&#39;,&#39;Quantum Silver&#39;)
console.log(car.toString())复制代码
Copy after login

Functional Programming

In the code below, the function

inner hides the fn and args .

function curry(fn) {
  const args = []
  return function inner(arg) {
    if(args.length === fn.length) return fn(...args)
    args.push(arg)
    return inner
  }
}

function add(a, b) {
  return a + b
}

const curriedAdd = curry(add)
console.log(curriedAdd(2)(3)()) // 5复制代码
Copy after login

Event-oriented programming

In the following code, the function

onClick hides the variable BACKGROUND_COLOR.

const $ = document.querySelector.bind(document)
const BACKGROUND_COLOR = &#39;rgba(200,200,242,1)&#39;

function onClick() {
  $(&#39;body&#39;).style.background = BACKGROUND_COLOR
}

$(&#39;button&#39;).addEventListener(&#39;click&#39;, onClick)复制代码
Copy after login
rrree

Modular

在下面的示例中,所有实现细节都隐藏在一个立即执行的函数表达式中。函数ticktoString隐藏了私有状态和函数,它们需要完成自己的工作。闭包使我们能够模块化和封装我们的代码。

let namespace = {};

(function foo(n) {
  let numbers = []
  function format(n) {
    return Math.trunc(n)
  }
  function tick() {
    numbers.push(Math.random() * 100)
  }
  function toString() {
    return numbers.map(format)
  }
  n.counter = {
    tick,
    toString
  }
}(namespace))

const counter = namespace.counter
counter.tick()
counter.tick()
console.log(counter.toString())复制代码
Copy after login

事例 1:

此示例演示局部变量未在闭包中复制。 闭包保留对原始变量本身的引用。 似乎即使外部函数退出后,堆栈仍在内存中保留。

function foo () {
  let x = 42
  let inner = function () {
    console.log(x)
  }
  x = x + 1
  return inner
}

let f = foo()
f()复制代码
Copy after login

事例 2:

在下面的代码中,三种方法logincrementupdate 都在同一词法环境闭包中。

function createObject() {
  let x = 42;
  return {
    log() { console.log(x) },
    increment() { x++ },
    update(value) { x = value }
  }
}

const o = createObject()
o.increment()
o.log() // 43
o.update(5)
o.log() // 5
const p = createObject()
p.log() // 42复制代码
Copy after login

事例 3:

如果使用的变量是使用var声明的,需要注意的一点是,使用var声明的变量被提升。 由于引入了letconst,这在现代JavaScript 中几乎没有问题。

在下面的代码中,每次循环中,都会创建一个新的inner函数,变量i被覆盖,但是因var会让 i 提升到函数的顶部,所以所有这些inner函数覆盖的都是同一个变量,这意味着i(3)的最终值被打印了三次。

function foo () {
  var result = []
  for (var i = 0; i < 3; i++) {
    result.push(function inner () {
      console.log(i)
    })
  }
  return result
}
const result = foo()

for(var i = 0; i < 3; i++) {
  result[i]()
}
// 3 3 3复制代码
Copy after login

最后一点:

  • 每当在JavaScript中声明函数时,都会创建一个闭包。

  • 从一个函数内部返回另一个函数是闭包的经典例子,因为外部函数内部的状态对于返回的内部函数是隐式可用的,即使外部函数已经完成执行。

  • 只要在函数内使用eval(),就会使用一个闭包。eval的文本可以引用函数的局部变量,在非严格模式下,甚至可以通过使用eval(&#39;var foo = &#39;)创建新的局部变量。

  • 当在函数内部使用new Function()(Function constructor)时,它不会覆盖其词法环境,而是覆盖全局上下文。新函数不能引用外部函数的局部变量。
  • 在JavaScript中,闭包类似于在函数声明时保留对作用域的引用(而不是复制),后者又保留对其外部作用域的引用,以此类推,一直到作用域链顶端的全局对象。
  • 声明函数时创建一个闭包。 当调用函数时,此闭包用于配置执行上下文。

  • 每次调用函数时都会创建一组新的局部变量。

JavaScript 中的每个函数都维护与其外部词法环境的链接。 词法环境是所有名称的映射(例如,变量,参数)及其范围内的值。因此,只要看到function关键字,函数内部的代码就可以访问在函数外部声明的变量。

function foo(x) {
  var tmp = 3;

  function bar(y) {
    console.log(x + y + (++tmp)); // 16
  }

  bar(10);
}

foo(2);复制代码
Copy after login

上面输出结果是16,参数x和变量tmp都存在于外部函数foo的词法环境中。函数bar及其与函数foo的词法环境的链接是一个闭包。

函数不必返回即可创建闭包。 仅仅凭借其声明,每个函数都会在其封闭的词法环境中关闭,从而形成一个闭包。

function foo(x) {
  var tmp = 3;

  return function (y) {
    console.log(x + y + (++tmp)); // 16
  }
}

var bar = foo(2);
bar(10); // 16
bar(10); // 17复制代码
Copy after login

上面还是打印16,因为bar内的代码仍然可以引用参数x和变量tmp,即使它们不再直接的作用域内。

但是,由于tmp仍然在bar的闭包内部徘徊,因此可以对其进行递增。 每次调用bar时,它将增加1

闭包最简单的例子是这样的:

var a = 10;

function test() {
  console.log(a); // will output 10
  console.log(b); // will output 6
}
var b = 6;
test();复制代码
Copy after login

当调用一个JavaScript函数时,将创建一个新的执行上下文ec。连同函数参数和目标对象,这个执行上下文还接收到调用执行上下文的词法环境的链接,这意味着在外部词法环境中声明的变量(在上面的例子中,ab)都可以从ec获得。

每个函数都会创建一个闭包,因为每个函数都有与其外部词法环境的链接。

注意,变量本身在闭包中是可见的,而不是副本。

4. use strict 在 JavaScript 中做了什么,背后的原因是什么

引用一些有趣的部分:

严格模式是ECMAScript 5中的一个新特性,它允许我们将程序或函数放置在严格的操作上下文中。这种严格的上下文会防止某些操作被执行,并引发更多异常。

严格模式在很多方面都有帮助:

  • 它捕获了一些常见的编码漏洞,并抛出异常。
  • 当采取相对不安全的操作(例如访问全局对象)时,它可以防止错误或抛出错误。
  • 它禁用令人困惑或考虑不周到的特性。

另外,请注意,我信可以将“strict mode”应用于整个文件,也可以仅将其用于特定函数。

// Non-strict code...

(function(){
  "use strict";

  // Define your library strictly...
})();

// Non-strict code... 
复制代码
Copy after login

如果是在混合使用旧代码和新代码的情况,这可能会有所帮助。它有点像在Perl中使用的“use strict”。通过检测更多可能导致损坏的东西,帮助我们减少更多的错误。

现在所有主流浏览器都支持严格模式。

在原生ECMAScript模块(带有importexport语句)和ES6类中,严格模式始终是启用的,不能禁用。

5.如何检查字符串是否包含子字符串?

ECMAScript 6 引入了string .prototype.include

const string = "foo";
const substring = "oo";

console.log(string.includes(substring));复制代码
Copy after login

不过,IE 不支持 includes。在 CMAScript 5或更早的环境中,使用String.prototype.indexOf。如果找不到子字符串,则返回-1:

var string = "foo";
var substring = "oo";

console.log(string.indexOf(substring) !== -1);复制代码
Copy after login

为了使其在旧的浏览器中运行,可以使用这种polyfill

if (!String.prototype.includes) {
  String.prototype.includes = function(search, start) {
    &#39;use strict&#39;;
    if (typeof start !== &#39;number&#39;) {
      start = 0;
    }

    if (start + search.length > this.length) {
      return false;
    } else {
      return this.indexOf(search, start) !== -1;
    }
  };
}复制代码
Copy after login

6. var functionName = function() {} 与 function functionName() {}

不同之处在于functionOne是一个函数表达式,因此只在到达这一行时才会定义,而functionTwo是一个函数声明,在它周围的函数或脚本被执行(由于提升)时就定义。

如,函数表达式

// TypeError: functionOne is not a function
functionOne();

var functionOne = function() {
  console.log("Hello!");
};复制代码
Copy after login

函数声明:

// "Hello!"
functionTwo();

function functionTwo() {
  console.log("Hello!");
}复制代码
Copy after login

过去,在不同的浏览器之间,在块中定义的函数声明的处理是不一致的。严格模式(在ES5中引入)解决了这个问题,它将函数声明的范围限定在其封闭的块上。

&#39;use strict&#39;;    
{ // note this block!
  function functionThree() {
    console.log("Hello!");
  }
}
functionThree(); // ReferenceError复制代码
Copy after login

function abc(){}也具有作用域-名称abc在遇到该定义的作用域中定义。 例:

function xyz(){
  function abc(){};
  // abc 在这里定义...
}
// ...不是在这里复制代码
Copy after login

如果想在所有浏览器上给函数起别名,可以这么做:

function abc(){};
var xyz = abc;复制代码
Copy after login

在本例中,xyz和abc都是同一个对象的别名

console.log(xyz === abc) // true复制代码
Copy after login

它的名称是自动分配的。但是当你定义它的时候

var abc = function(){};
console.log(abc.name); //  ""复制代码
Copy after login

它的name称为空,我们创建了一个匿名函数并将其分配给某个变量。使用组合样式的另一个很好的理由是使用简短的内部名称来引用自身,同时为外部用户提供一个长而不会冲突的名称:

// 假设 really.long.external.scoped 为 {}
really.long.external.scoped.name = function shortcut(n){
  // 它递归地调用自己:
  shortcut(n - 1);
  // ...
  // 让它自己作为回调传递::
  someFunction(shortcut);
  // ...
}复制代码
Copy after login

在上面的例子中,我们可以对外部名称进行同样的操作,但是这样做太笨拙了(而且速度更慢)。另一种引用自身的方法是arguments.callee,这种写法也相对较长,并且在严格模式中不受支持。

实际上,JavaScript对待这两个语句是不同的。下面是一个函数声明:

function abc(){}复制代码
Copy after login

这里的abc可以定义在当前作用域的任何地方:

// 我们可以在这里调用
abc(); 

// 在这里定义
function abc(){}

// 也可以在这里调用 
abc(); 
复制代码
Copy after login

此外,尽管有 return 语句,也可以提升:

// 我们可以在这里调用
abc(); 
return;
function abc(){}复制代码
Copy after login

下面是一个函数表达式:

var xyz = function(){};复制代码
Copy after login

这里的xyz是从赋值点开始定义的:

// 我们不可以在这里调用
xyz(); 

// 在这里定义 xyz
xyz = function(){}

// 我们可以在这里调用
xyz(); 
复制代码
Copy after login

函数声明与函数表达式之间存在差异的真正原因。

var xyz = function abc(){};
console.log(xyz.name); // "abc"复制代码
Copy after login

就个人而言,我们更喜欢使用函数表达式声明,因为这样可以控制可见性。当我们像这样定义函数时:

var abc = function(){};复制代码
Copy after login

我们知道,如果我们没有在作用域链的任何地方定义abc,那么我们是在全局作用域内定义的。即使在eval()内部使用,这种类型的定义也具有弹性。而定义:

function abc(){};复制代码
Copy after login

取决于上下文,并且可能让你猜测它的实际定义位置,特别是在eval()的情况下,—取决于浏览器。

7.如何从 JavaScript 对象中删除属性?

我们可以这样删除对象的属性:

delete myObject.regex;
// 或者
delete myObject[&#39;regex&#39;];
//  或者
var prop = "regex";
delete myObject[prop];复制代码
Copy after login

事例:

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};
delete myObject.regex;

console.log(myObject);复制代码
Copy after login

JavaScript 中的对象可以看作键和值之间的映射。delete操作符用于一次删除一个键(通常称为对象属性)。

var obj = {
  myProperty: 1    
}
console.log(obj.hasOwnProperty(&#39;myProperty&#39;)) // true
delete obj.myProperty
console.log(obj.hasOwnProperty(&#39;myProperty&#39;)) // false复制代码
Copy after login

delete 操作符不是直接释放内存,它不同于简单地将nullundefined值赋给属性,而是将属性本身从对象中删除。

注意,如果已删除属性的值是引用类型(对象),而程序的另一部分仍然持有对该对象的引用,那么该对象当然不会被垃圾收集,直到对它的所有引用都消失。

delete只对其描述符标记为configurable的属性有效。

8. JS 的比较中应使用哪个等于运算符(== vs ===)?

严格相等运算符(===)的行为与抽象相等运算符(==)相同,除非不进行类型转换,而且类型必须相同才能被认为是相等的。

==运算符会进行类型转换后比较相等性。 ===运算符不会进行转换,因此如果两个值的类型不同,则===只会返回false。

JavaScript有两组相等运算符:===!==,以及它们的孪生兄弟==!=。如果这两个操作数具有相同的类型和相同的值,那么===的结果就是 true,而!==的结果就是 false

下面是一些事例:

&#39;&#39; == &#39;0&#39;           // false
0 == &#39;&#39;             // true
0 == &#39;0&#39;            // true

false == &#39;false&#39;    // false
false == &#39;0&#39;        // true

false == undefined  // false
false == null       // false
null == undefined   // true

&#39; \t\r\n &#39; == 0     // true复制代码
Copy after login

上面有些看起来会挺困惑的,所以尽量还是使用严格比较运算符(===)。对于引用类型,=====操作一致(特殊情况除外)。

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true复制代码
Copy after login

特殊情况是,当你将一个字符串字面量与一个字符串对象进行比较时,由于该对象的toStringvalueOf方法,该对象的值与相字面量的值一样。

考虑将字符串字面量与由String构造函数创建的字符串对象进行比较:

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false复制代码
Copy after login

在这里,==操作符检查两个对象的值并返回true,但是===看到它们不是同一类型并返回false。哪一个是正确的?这取决于你想要比较的是什么。

我们的建议是完全绕开该问题,只是不要使用String构造函数来创建字符串对象。

使用==运算符(等于)

true == 1; //true, 因为 true 被转换为1,然后进行比较
"2" == 2;  //true, 因为 “2” 被转换成 2,然后进行比较复制代码
Copy after login

使用===操作符

true === 1; //false
"2" === 2;  //false复制代码
Copy after login

9.在 JavaScript 中深拷贝一个对象的最有效方法是什么?

快速克隆,数据丢失– JSON.parse/stringify

如果您没有在对象中使用Date、函数、undefinedInfinityRegExpMapSet、blob、、稀疏数组、类型化数组或其他复杂类型,那么可以使用一行简单代码来深拷贝一个对象:

JSON.parse(JSON.stringify(object))复制代码
Copy after login
const a = {
  string: &#39;string&#39;,
  number: 123,
  bool: false,
  nul: null,
  date: new Date(), 
  undef: undefined,  // 丢失
  inf: Infinity,  // 被设置为 null
  re: /.*/,  // 丢失
}
console.log(a);
console.log(typeof a.date);  // object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
/*
object
{
  string: &#39;string&#39;,
  number: 123,
  bool: false,
  nul: null,
  date: &#39;2020-09-04T00:45:41.823Z&#39;,
  inf: null,
  re: {}
}

*/
console.log(typeof clone.date);  // string复制代码
Copy after login

使用库进行可靠的克隆

由于克隆对象不是一件简单的事情(复杂类型、循环引用、函数等等),大多数主要的库都提供了拷贝对象的函数。如果你已经在使用一个库,请检查它是否具有对象克隆功能。例如

  • lodashcloneDeep; 可以通过lodash.clonedeep模块单独导入,如果你尚未使用提供深拷贝功能的库,那么它可能是你的最佳选择

  • AngularJS – angular.copy

  • jQuery – jQuery.extend(true, { }, oldObject); .clone()仅克隆DOM元素

ES6

ES6 提供了两种浅拷贝机制:Object.assign()spread语法。它将所有可枚举的自有属性的值从一个对象复制到另一个对象。例如

var A1 = {a: "2"};
var A2 = Object.assign({}, A1);
var A3 = {...A1};  // Spread Syntax复制代码
Copy after login

在以前的测试中,速度是最主要的问题

JSON.parse(JSON.stringify(obj))复制代码
Copy after login

这是深拷贝对象的最慢方法,它比jQuery.extend慢 10-20%。

deep标志设置为false(浅克隆)时,jQuery.extend非常快。 这是一个不错的选择,因为它包括一些用于类型验证的额外逻辑,并且不会复制未定义的属性等,但这也会使你的速度变慢。

如果想拷贝的一个对象且你知道对象结构。那么,你可以写一个简单的for (var i in obj)循环来克隆你的对象,同时检查hasOwnProperty,这将比jQuery快得多。

var clonedObject = {
  knownProp: obj.knownProp,
  ..
}复制代码
Copy after login

注意在 Date 对象JSON上使用JSON.parse(JSON.stringify(obj))方法。JSON.stringify(new Date())以ISO格式返回日期的字符串表示,JSON.parse()不会将其转换回Date对象。

10.如何在另一个JavaScript文件中包含一个JavaScript文件?

旧版本的JavaScript没有importincluderequire,因此针对这个问题开发了许多不同的方法。

但是从2015年(ES6)开始,JavaScript已经有了ES6模块标准,可以在Node中导入模块。为了与旧版浏览器兼容,可以使用WebpackRollup之类的构建工具和/或Babel这样的编译工具。

ES6 Module

从v8.5开始,Node.js就支持ECMAScript (ES6)模块,带有--experimental-modules 标志,而且至少Node.js v13.8.0没有这个标志。要启用ESM(相对于Node.js之前的commonjs风格的模块系统[CJS]),你可以在 package.json中使用“type”:“module”。或者为文件提供扩展名.mjs。(类似地,如果默认为ESM,则用 Node.js 以前的CJS模块编写的模块可以命名为.cjs。)

使用package.json

{
    "type": "module"
}复制代码
Copy after login

module.js:

export function hello() {
  return "Hello";
}复制代码
Copy after login
Copy after login

main.js:

import { hello } from &#39;./module.js&#39;;
let val = hello();  // val is "Hello";复制代码
Copy after login

使用.mjs,会有对应的module.mjs

export function hello() {
  return "Hello";
}复制代码
Copy after login
Copy after login

main.mjs

import { hello } from &#39;./module.mjs&#39;;
let val = hello();  // val is "Hello";复制代码
Copy after login

自Safari 10.1,Chrome 61,Firefox 60 和 Edge 16 开始,浏览器就已经支持直接加载ECMAScript模块(不需要像Webpack这样的工具)。无需使用Node.js的.mjs扩展名; 浏览器完全忽略模块/脚本上的文件扩展名。

<script type="module">
  import { hello } from &#39;./hello.mjs&#39;; // Or it could be simply `hello.js`
  hello(&#39;world&#39;);
</script>复制代码
Copy after login
// hello.mjs -- or it could be simply `hello.js`
export function hello(text) {
  const p = document.createElement(&#39;p&#39;);
  p.textContent = `Hello ${text}`;
  document.body.appendChild(p);
}复制代码
Copy after login

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】。

浏览器中的动态导入

动态导入允许脚本根据需要加载其他脚本

<script type="module">
  import(&#39;hello.mjs&#39;).then(module => {
      module.hello(&#39;world&#39;);
    });
</script>复制代码
Copy after login

Node.js require

在 Node.js 中用的较多还是 module.exports/require

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}复制代码
Copy after login

// server.js const myModule = require(&#39;./mymodule&#39;); let val = myModule.hello(); // val is "Hello"

动态加载文件

我们可以通过动态创建 script 来动态引入文件:

function dynamicallyLoadScript(url) {
    var script = document.createElement("script"); 

    document.head.appendChild(script); 
}复制代码
Copy after login

检测脚本何时执行

现在,有一个个大问题。上面这种动态加载都是异步执行的,这样可以提高网页的性能。 这意味着不能在动态加载下马上使用该资源,因为它可能还在加载。

例如:my_lovely_script.js包含MySuperObject

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined复制代码
Copy after login

然后,按F5重新加载页面,可能就有效了。那么该怎么办呢?

我们可以使用回调函数来解决些问题。

function loadScript(url, callback)
{
    var head = document.head;
    var script = document.createElement(&#39;script&#39;);
    script.type = &#39;text/javascript&#39;;
    script.src = url;

    script.onload = callback;

    head.appendChild(script);
}复制代码
Copy after login

然后编写在lambda函数中加载脚本后要使用的代码

var myPrettyCode = function() {
   // Here, do whatever you want
};复制代码
Copy after login

然后,运行代码:

loadScript("my_lovely_script.js", myPrettyCode);复制代码
Copy after login

请注意,脚本可能在加载DOM之后或之前执行,具体取决于浏览器以及是否包括行script.async = false;

相关免费学习推荐:javascript(视频)

The above is the detailed content of 10 basic questions you must master in JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:juejin.im
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!