1.1w字 | 初中级前端 JavaScript 自测清单 - 2 下

简介: 1.1w字 | 初中级前端 JavaScript 自测清单 - 2 下

五、构造函数和 new 运算符

1. 构造函数

构造函数的作用在于 实现可重用的对象创建代码 。 通常,对于构造函数有两个约定:

  • 命名时首字母大写;
  • 只能使用 new 运算符执行。

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。 语法如下:

new constructor[([arguments])]

参数如下:

  • constructor一个指定对象实例的类型的类或函数。
  • arguments一个用于被 constructor 调用的参数列表。

2. 简单示例

举个简单示例:

function User (name){
  this.name = name;
  this.isAdmin = false; 
}
const leo = new User('leo');
console.log(leo.name, leo.isAdmin); // "leo" false

3. new 运算符操作过程

当一个函数被使用 new 运算符执行时,它按照以下步骤:

  1. 一个新的空对象被创建并分配给 this
  2. 函数体执行。通常它会修改 this,为其添加新的属性。
  3. 返回 this 的值。

以前面 User 方法为例:

function User(name) {
  // this = {};(隐式创建)
  // 添加属性到 this
  this.name = name;
  this.isAdmin = false;
  // return this;(隐式返回)
}
const leo = new User('leo');
console.log(leo.name, leo.isAdmin); // "leo" false

当我们执行 new User('leo') 时,发生以下事情:

  1. 一个继承自 User.prototype 的新对象被创建;
  2. 使用指定参数调用构造函数 User ,并将 this 绑定到新创建的对象;
  3. 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。

需要注意

  1. 一般情况下,构造函数不返回值,但是开发者可以选择主动返回对象,来覆盖正常的对象创建步骤;
  2. new User 等同于 new User() ,只是没有指定参数列表,即 User 不带参数的情况;
let user = new User; // <-- 没有参数
// 等同于
let user = new User();
  1. 任何函数都可以作为构造器,即都可以使用 new 运算符运行。

4. 构造函数中的方法

在构造函数中,也可以将方法绑定到 this 上:

function User (name){
  this.name = name;
  this.isAdmin = false; 
  this.sayHello = function(){
    console.log("hello " + this.name);
  }
}
const leo = new User('leo');
console.log(leo.name, leo.isAdmin); // "leo" false
leo.sayHello(); // "hello leo"

六、可选链 "?."

详细介绍可以查看 《MDN 可选链操作符》

1. 背景介绍

在实际开发中,常常出现下面几种报错情况:

// 1. 对象中不存在指定属性
const leo = {};
console.log(leo.name.toString()); 
// Uncaught TypeError: Cannot read property 'toString' of undefined
// 2. 使用不存在的 DOM 节点属性
const dom = document.getElementById("dom").innerHTML; 
// Uncaught TypeError: Cannot read property 'innerHTML' of null

在可选链 ?. 出现之前,我们会使用短路操作 && 运算符来解决该问题:

const leo = {};
console.log(leo && leo.name && leo.name.toString()); // undefined

这种写法的缺点就是 太麻烦了

2. 可选链介绍

可选链 ?. 是一种 访问嵌套对象属性的防错误方法 。即使中间的属性不存在,也不会出现错误。 如果可选链 ?. 前面部分是 undefined 或者 null,它会停止运算并返回 undefined

语法:

obj?.prop
obj?.[expr]
arr?.[index]
func?.(args)

** 我们改造前面示例代码:

// 1. 对象中不存在指定属性
const leo = {};
console.log(leo?.name?.toString()); 
// undefined
// 2. 使用不存在的 DOM 节点属性
const dom = document?.getElementById("dom")?.innerHTML; 
// undefined

3. 使用注意

可选链虽然好用,但需要注意以下几点:

  1. 不能过度使用可选链

我们应该只将 ?. 使用在一些属性或方法可以不存在的地方,以上面示例代码为例:

const leo = {};
console.log(leo.name?.toString()); 

这样写会更好,因为 leo 对象是必须存在,而 name 属性则可能不存在。

  1. 可选链 ?. 之前的变量必须已声明

在可选链 ?. 之前的变量必须使用 let/const/var 声明,否则会报错:

leo?.name;
// Uncaught ReferenceError: leo is not defined
  1. 可选链不能用于赋值
let object = {};
object?.property = 1; 
// Uncaught SyntaxError: Invalid left-hand side in assignment
  1. 可选链访问数组元素的方法
let arrayItem = arr?.[42];

4. 其他情况:?.() 和 ?.[]

需要说明的是 ?. 是一个特殊的语法结构,而不是一个运算符,它还可以与其 ()[] 一起使用:

4.1 可选链与函数调用 ?.()

?.() 用于调用一个可能不存在的函数,比如:

let user1 = {
  admin() {
    alert("I am admin");
  }
}
let user2 = {};
user1.admin?.(); // I am admin
user2.admin?.();

?.() 会检查它左边的部分:如果 admin 函数存在,那么就调用运行它(对于 user1)。否则(对于 user2)运算停止,没有错误。

4.2 可选链和表达式 ?.[]

?.[] 允许从一个可能不存在的对象上安全地读取属性。

let user1 = {
  firstName: "John"
};
let user2 = null; // 假设,我们不能授权此用户
let key = "firstName";
alert( user1?.[key] ); // John
alert( user2?.[key] ); // undefined
alert( user1?.[key]?.something?.not?.existing); // undefined

5. 可选链 ?. 语法总结

可选链 ?. 语法有三种形式:

  1. obj?.prop —— 如果 obj 存在则返回 obj.prop,否则返回 undefined
  2. obj?.[prop] —— 如果 obj 存在则返回 obj[prop],否则返回 undefined
  3. obj?.method() —— 如果 obj 存在则调用 obj.method(),否则返回 undefined

正如我们所看到的,这些语法形式用起来都很简单直接。?. 检查左边部分是否为 null/undefined,如果不是则继续运算。 ?. 链使我们能够安全地访问嵌套属性。

七、Symbol

规范规定,JavaScript 中对象的属性只能为 字符串类型 或者 Symbol类型 ,毕竟我们也只见过这两种类型。

1. 概念介绍

ES6引入Symbol作为一种新的原始数据类型,表示独一无二的值,主要是为了防止属性名冲突。 ES6之后,JavaScript一共有其中数据类型:SymbolundefinednullBooleanStringNumberObject简单使用

let leo = Symbol();
typeof leo; // "symbol"

Symbol 支持传入参数作为 Symbol 名,方便代码调试: **

let leo = Symbol("leo");

2. 注意事项**

  • Symbol函数不能用new,会报错。

由于Symbol是一个原始类型,不是对象,所以不能添加属性,它是类似于字符串的数据类型。

let leo = new Symbol()
// Uncaught TypeError: Symbol is not leo constructor
  • Symbol都是不相等的,即使参数相同
// 没有参数
let leo1 = Symbol();
let leo2 = Symbol();
leo1 === leo2; // false 
// 有参数
let leo1 = Symbol('leo');
let leo2 = Symbol('leo');
leo1 === leo2; // false
  • Symbol不能与其他类型的值计算,会报错。
let leo = Symbol('hello');
leo + " world!";  // 报错
`${leo} world!`;  // 报错
  • Symbol 不能自动转换为字符串,只能显式转换。
let leo = Symbol('hello');
alert(leo); 
// Uncaught TypeError: Cannot convert a Symbol value to a string
String(leo);    // "Symbol(hello)"
leo.toString(); // "Symbol(hello)"
  • Symbol 可以转换为布尔值,但不能转为数值:
let a1 = Symbol();
Boolean(a1);
!a1;        // false
Number(a1); // TypeError
a1 + 1 ;    // TypeError
  • Symbol 属性不参与 for...in/of 循环。
let id = Symbol("id");
let user = {
  name: "Leo",
  age: 30,
  [id]: 123
};
for (let key in user) console.log(key); // name, age (no symbols)
// 使用 Symbol 任务直接访问
console.log( "Direct: " + user[id] );

3. 字面量中使用 Symbol 作为属性名

在对象字面量中使用 Symbol 作为属性名时,需要使用 方括号[] ),如 [leo]: "leo" 。 好处:防止同名属性,还有防止键被改写或覆盖。

let leo = Symbol();
// 写法1
let user = {};
user[leo] = 'leo';
// 写法2
let user = {
    [leo] : 'leo'
} 
// 写法3
let user = {};
Object.defineProperty(user, leo, {value : 'leo' });
// 3种写法 结果相同
user[leo]; // 'leo'

需要注意 :Symbol作为对象属性名时,不能用点运算符,并且必须放在方括号内。

let leo = Symbol();
let user = {};
// 不能用点运算
user.leo = 'leo';
user[leo] ; // undefined
user['leo'] ; // 'leo'
// 必须放在方括号内
let user = {
    [leo] : function (text){
        console.log(text);
    }
}
user[leo]('leo'); // 'leo'
// 上面等价于 更简洁
let user = {
    [leo](text){
        console.log(text);
    }
}

常常还用于创建一组常量,保证所有值不相等

let user = {};
user.list = {
    AAA: Symbol('Leo'),
    BBB: Symbol('Robin'),
    CCC: Symbol('Pingan')
}

4. 应用:消除魔术字符串

魔术字符串:指代码中多次出现,强耦合的字符串或数值,应该避免,而使用含义清晰的变量代替。

function fun(name){
    if(name == 'leo') {
        console.log('hello');
    }
}
fun('leo');   // 'hello' 为魔术字符串

常使用变量,消除魔术字符串:

let obj = {
    name: 'leo'
};
function fun(name){
    if(name == obj.name){
        console.log('hello');
    }
}
fun(obj.name); // 'hello'

使用Symbol消除强耦合,使得不需关系具体的值:

let obj = {
    name: Symbol()
};
function fun (name){
    if(name == obj.name){
        console.log('hello');
    }
}
fun(obj.name); // 'hello'

5. 属性名遍历

Symbol作为属性名遍历,不出现在for...infor...of循环,也不被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回。

let leo = Symbol('leo'), robin = Symbol('robin');
let user = {
    [leo]:'18', [robin]:'28'
}
for(let k of Object.values(user)){console.log(k)}
// 无输出
let user = {};
let leo = Symbol('leo');
Object.defineProperty(user, leo, {value: 'hi'});
for(let k in user){
    console.log(k); // 无输出
}
Object.getOwnPropertyNames(user);   // []
Object.getOwnPropertySymbols(user); // [Symbol(leo)]

Object.getOwnPropertySymbols方法返回一个数组,包含当前对象所有用做属性名的Symbol值。

let user = {};
let leo = Symbol('leo');
let pingan = Symbol('pingan');
user[leo] = 'hi leo';
user[pingan] = 'hi pingan';
let obj = Object.getOwnPropertySymbols(user);
obj; //  [Symbol(leo), Symbol(pingan)]

另外可以使用Reflect.ownKeys方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。

let user = {
    [Symbol('leo')]: 1,
    age : 2, 
    address : 3,
}
Reflect.ownKeys(user); // ['age', 'address',Symbol('leo')]

由于Symbol值作为名称的属性不被常规方法遍历获取,因此常用于定义对象的一些非私有,且内部使用的方法。

6. Symbol.for()、Symbol.keyFor()

6.1 Symbol.for()

用于重复使用一个Symbol值,接收一个字符串作为参数,若存在用此参数作为名称的Symbol值,返回这个Symbol,否则新建并返回以这个参数为名称的Symbol值。

let leo = Symbol.for('leo');
let pingan = Symbol.for('leo');
leo === pingan;  // true

Symbol()Symbol.for()区别:

Symbol.for('leo') === Symbol.for('leo'); // true
Symbol('leo') === Symbol('leo');         // false

6.2 Symbol.keyFor()

用于返回一个已使用的Symbol类型的key:

let leo = Symbol.for('leo');
Symbol.keyFor(leo);   //  'leo'
let leo = Symbol('leo');
Symbol.keyFor(leo);   //  undefined

7. 内置的Symbol值

ES6提供11个内置的Symbol值,指向语言内部使用的方法:

7.1 Symbol.hasInstance

当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)

class P {
    [Symbol.hasInstance](a){
        return a instanceof Array;
    }
}
[1, 2, 3] instanceof new P(); // true

P是一个类,new P()会返回一个实例,该实例的Symbol.hasInstance方法,会在进行instanceof运算时自动调用,判断左侧的运算子是否为Array的实例。

7.2 Symbol.isConcatSpreadable

值为布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。

let a = ['aa','bb'];
['cc','dd'].concat(a, 'ee'); 
// ['cc', 'dd', 'aa', 'bb', 'ee']
a[Symbol.isConcatSpreadable]; // undefined
let b = ['aa','bb']; 
b[Symbol.isConcatSpreadable] = false; 
['cc','dd'].concat(b, 'ee'); 
// ['cc', 'dd',[ 'aa', 'bb'], 'ee']

7.3 Symbol.species

指向一个构造函数,在创建衍生对象时会使用,使用时需要用get取值器。

class P extends Array {
    static get [Symbol.species](){
        return this;
    }
}

解决下面问题:

// 问题:  b应该是 Array 的实例,实际上是 P 的实例
class P extends Array{}
let a = new P(1,2,3);
let b = a.map(x => x);
b instanceof Array; // true
b instanceof P; // true
// 解决:  通过使用 Symbol.species
class P extends Array {
  static get [Symbol.species]() { return Array; }
}
let a = new P();
let b = a.map(x => x);
b instanceof P;     // false
b instanceof Array; // true

7.4 Symbol.match

当执行str.match(myObject),传入的属性存在时会调用,并返回该方法的返回值。

class P {
    [Symbol.match](string){
        return 'hello world'.indexOf(string);
    }
}
'h'.match(new P());   // 0

7.5 Symbol.replace

当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。

let a = {};
a[Symbol.replace] = (...s) => console.log(s);
'Hello'.replace(a , 'World') // ["Hello", "World"]

7.6 Symbol.hasInstance

当该对象被String.prototype.search方法调用时,会返回该方法的返回值。

class P {
    constructor(val) {
        this.val = val;
    }
    [Symbol.search](s){
        return s.indexOf(this.val);
    }
}
'hileo'.search(new P('leo')); // 2

7.7 Symbol.split

当该对象被String.prototype.split方法调用时,会返回该方法的返回值。

// 重新定义了字符串对象的split方法的行为
class P {
    constructor(val) {
        this.val = val;
    }
    [Symbol.split](s) {
        let i = s.indexOf(this.val);
        if(i == -1) return s;
        return [
            s.substr(0, i),
            s.substr(i + this.val.length)
        ]
    }
}
'helloworld'.split(new P('hello')); // ["hello", ""]
'helloworld'.split(new P('world')); // ["", "world"] 
'helloworld'.split(new P('leo'));   // "helloworld"

7.8 Symbol.iterator

对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器。

class P {
    *[Symbol.interator]() {
        let i = 0;
        while(this[i] !== undefined ) {
            yield this[i];
            ++i;
        }
    }
}
let a = new P();
a[0] = 1;
a[1] = 2;
for (let k of a){
    console.log(k);
}

7.9.Symbol.toPrimitive

该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。调用时,需要接收一个字符串参数,表示当前运算模式,运算模式有:

  • Number : 此时需要转换成数值
  • String : 此时需要转换成字符串
  • Default : 此时可以转换成数值或字符串
let obj = {
  [Symbol.toPrimitive](hint) {
    switch (hint) {
      case 'number':
        return 123;
      case 'string':
        return 'str';
      case 'default':
        return 'default';
      default:
        throw new Error();
     }
   }
};
2 * obj // 246
3 + obj // '3default'
obj == 'default' // true
String(obj) // 'str'

7.10 Symbol.toStringTag

在该对象上面调用Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[object Object]或[object Array]object后面的那个字符串。

// 例一
({[Symbol.toStringTag]: 'Foo'}.toString())
// "[object Foo]"
// 例二
class Collection {
  get [Symbol.toStringTag]() {
    return 'xxx';
  }
}
let x = new Collection();
Object.prototype.toString.call(x) // "[object xxx]"

7.11 Symbol.unscopables

该对象指定了使用with关键字时,哪些属性会被with环境排除。

// 没有 unscopables 时
class MyClass {
  foo() { return 1; }
}
var foo = function () { return 2; };
with (MyClass.prototype) {
  foo(); // 1
}
// 有 unscopables 时
class MyClass {
  foo() { return 1; }
  get [Symbol.unscopables]() {
    return { foo: true };
  }
}
var foo = function () { return 2; };
with (MyClass.prototype) {
  foo(); // 2
}

上面代码通过指定Symbol.unscopables属性,使得with语法块不会在当前作用域寻找foo属性,即foo将指向外层作用域的变量。

八、原始值转换

前面复习到字符串、数值、布尔值等的转换,但是没有讲到对象的转换规则,这部分就一起看看:。 需要记住几个规则:

  1. 所有对象在布尔上下文中都为 true ,并且不存在转换为布尔值的操作,只有字符串和数值转换有。
  2. 数值转换发生在对象相减或应用数学函数时。如 Date 对象可以相减,如 date1 - date2 结果为两个时间的差值。
  3. 在字符串转换,通常出现在如 alert(obj) 这种形式。

当然我们可以使用特殊的对象方法,对字符串和数值转换进行微调。下面介绍三个类型(hint)转换情况:

1. object to string

对象到字符串的转换,当我们对期望一个字符串的对象执行操作时,如 “alert”:

// 输出
alert(obj);
// 将对象作为属性键
anotherObj[obj] = 123;

2. object to number

对象到数字的转换,例如当我们进行数学运算时:

// 显式转换
let num = Number(obj);
// 数学运算(除了二进制加法)
let n = +obj; // 一元加法
let delta = date1 - date2;
// 小于/大于的比较
let greater = user1 > user2;

3. object to default

少数情况下,当运算符“不确定”期望值类型时。 例如,二进制加法 + 可用于字符串(连接),也可以用于数字(相加),所以字符串和数字这两种类型都可以。因此,当二元加法得到对象类型的参数时,它将依据 "default" 来对其进行转换。 此外,如果对象被用于与字符串、数字或 symbol 进行 == 比较,这时到底应该进行哪种转换也不是很明确,因此使用 "default"

// 二元加法使用默认 hint
let total = obj1 + obj2;
// obj == number 使用默认 hint
if (user == 1) { ... };

4. 类型转换算法

为了进行转换,JavaScript 尝试查找并调用三个对象方法:

  1. 调用 obj[Symbol.toPrimitive](hint) —— 带有 symbol 键 Symbol.toPrimitive(系统 symbol)的方法,如果这个方法存在的话,
  2. 否则,如果 hint 是 "string" —— 尝试 obj.toString()obj.valueOf(),无论哪个存在。
  3. 否则,如果 hint 是 "number""default" —— 尝试 obj.valueOf()obj.toString(),无论哪个存在。

5. Symbol.toPrimitive

详细介绍可阅读《MDN | Symbol.toPrimitive》Symbol.toPrimitive 是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用此函数。 简单示例介绍:

let user = {
  name: "Leo",
  money: 9999,
  [Symbol.toPrimitive](hint) {
    console.log(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.money;
  }
};
alert(user);     // 控制台:hint: string 弹框:{name: "John"}
alert(+user);    // 控制台:hint: number 弹框:9999
alert(user + 1); // 控制台:hint: default 弹框:10000

6. toString/valueOf

toString / valueOf 是两个比较早期的实现转换的方法。当没有 Symbol.toPrimitive ,那么 JavaScript 将尝试找到它们,并且按照下面的顺序进行尝试:

  • 对于 “string” hint,toString -> valueOf
  • 其他情况,valueOf -> toString

这两个方法必须返回一个原始值。如果 toStringvalueOf 返回了一个对象,那么返回值会被忽略。默认情况下,普通对象具有 toStringvalueOf 方法:

  • toString 方法返回一个字符串 "[object Object]"
  • valueOf 方法返回对象自身。

简单示例介绍:

const user = {name: "Leo"};
alert(user); // [object Object]
alert(user.valueOf() === user); // true

我们也可以结合 toString / valueOf  实现前面第 5 点介绍的 user 对象:

let user = {
  name: "Leo",
  money: 9999,
  // 对于 hint="string"
  toString() {
    return `{name: "${this.name}"}`;
  },
  // 对于 hint="number" 或 "default"
  valueOf() {
    return this.money;
  }
};
alert(user);     // 控制台:hint: string 弹框:{name: "John"}
alert(+user);    // 控制台:hint: number 弹框:9999
alert(user + 1); // 控制台:hint: default 弹框:10000

总结

本文作为《初中级前端 JavaScript 自测清单》第二部分,介绍的内容以 JavaScript 对象为主,其中有让我眼前一亮的知识点,如 Symbol.toPrimitive 方法。我也希望这个清单能帮助大家自测自己的 JavaScript 水平并查缺补漏,温故知新。

目录
相关文章
|
4天前
|
资源调度 前端开发 JavaScript
vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
【11月更文挑战第10天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤,包括安装依赖、创建混淆脚本、修改 `package.json` 脚本命令、构建项目并执行混淆,以及在 HTML 文件中引用混淆后的文件。通过这些步骤,可以有效提高代码的安全性。
|
12天前
|
设计模式 前端开发 JavaScript
揭秘!前端大牛们如何巧妙利用JavaScript,打造智能交互体验!
【10月更文挑战第30天】前端开发领域充满了无限可能与创意,JavaScript作为核心语言,凭借强大的功能和灵活性,成为打造智能交互体验的重要工具。本文介绍前端大牛如何利用JavaScript实现平滑滚动、复杂动画、实时数据更新和智能表单验证等效果,展示了JavaScript的多样性和强大能力。
29 4
|
10天前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
|
10天前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
17 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
15天前
|
JavaScript 前端开发 开发者
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第27天】在前端开发领域,Vue.js和Angular是两个备受瞩目的框架。本文对比了两者的优劣,Vue.js以轻量级和易上手著称,适合快速开发小型到中型项目;Angular则由Google支持,功能全面,适合大型企业级应用。选择时需考虑项目需求、团队熟悉度和长期维护等因素。
21 1
|
16天前
|
JavaScript 前端开发 API
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第26天】前端技术的飞速发展让开发者在构建用户界面时有了更多选择。本文对比了Vue.js和Angular两大框架,介绍了它们的特点和优劣,并给出了在实际项目中如何选择的建议。Vue.js轻量级、易上手,适合小型项目;Angular结构化、功能强大,适合大型项目。
15 1
|
26天前
|
前端开发 JavaScript 安全
JavaScript前端开发技术
JavaScript(简称JS)是一种广泛使用的脚本语言,特别在前端开发领域,它几乎成为了网页开发的标配。从简单的表单验证到复杂的单页应用(SPA),JavaScript都扮演着不可或缺的角色。
19 3
|
7天前
|
前端开发 JavaScript 安全
vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
【11月更文挑战第7天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤。包括项目准备、安装 `javascript-obfuscator`、配置 Vite 构建以应用混淆,以及最终构建项目进行混淆。通过这些步骤,可以有效提升前端代码的安全性,防止被他人轻易分析和盗用。
|
19天前
|
前端开发 JavaScript UED
"前端小技巧大揭秘:JS如何将后台时间戳秒变亲切小时前、分钟前,让用户秒懂,提升互动体验!"
【10月更文挑战第23天】在Web开发中,将后台返回的时间戳转换为“小时前”、“分钟前”、“刚刚”等友好的时间描述是常见需求。本文介绍如何用JavaScript实现这一功能,通过计算当前时间和时间戳的差值,返回相应的描述,提升用户体验。
25 1
|
30天前
|
JavaScript 前端开发 应用服务中间件
vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法
vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法
137 0