手撕面试官,初中级前端 JavaScript 自测清单 - 2,字节跳动正式启动2024届秋季校招

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,

};

for (let key in user) console.log(key); // name, age (no symbols)

// 使用 Symbol 任务直接访问

console.log( "Direct: " + userid );

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


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

let leo = Symbol();

// 写法1

let user = {};

userleo = ‘leo’;

// 写法2

let user = {

leo : ‘leo’

}

// 写法3

let user = {};

Object.defineProperty(user, leo, {value : ‘leo’ });

// 3种写法 结果相同

userleo; // ‘leo’

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

let leo = Symbol();

let user = {};

// 不能用点运算

user.leo = ‘leo’;

userleo ; // undefined

user[‘leo’] ; // ‘leo’

// 必须放在方括号内

let user = {

leo : function (text){

console.log(text);

}

}

userleo; // ‘leo’

// 上面等价于 更简洁

let user = {

leo{

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 = {

}

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’);

userleo = ‘hi leo’;

user[pingan] = ‘hi pingan’;

let obj = Object.getOwnPropertySymbols(user);

obj; //  [Symbol(leo), Symbol(pingan)]

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

let user = {

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(‘pingan’);

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{

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{

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{

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 {

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 {

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后面的那个字符串。

// 例一

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

专业技能

一般来说,面试官会根据你的简历内容去提问,但是技术基础还有需要自己去准备分类,形成自己的知识体系的。简单列一下我自己遇到的一些题

最近得空把之前遇到的面试题做了一个整理,包括我本人自己去面试遇到的,还有其他人员去面试遇到的,还有网上刷到的,我都统一的整理了一下,希望对大家有用。

其中包含HTML、CSS、JavaScript、服务端与网络、Vue、浏览器等等

由于文章篇幅有限,仅展示部分内容

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

// 例一

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-VDxmseKs-1712319199439)]
[外链图片转存中…(img-HzgxNgMJ-1712319199440)]
[外链图片转存中…(img-QPUAgnx6-1712319199440)]
[外链图片转存中…(img-2DWXWcDj-1712319199440)]
[外链图片转存中…(img-Klfg6g8B-1712319199440)]
[外链图片转存中…(img-jm2n4XNq-1712319199441)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-hjw6R0D4-1712319199441)]

专业技能

一般来说,面试官会根据你的简历内容去提问,但是技术基础还有需要自己去准备分类,形成自己的知识体系的。简单列一下我自己遇到的一些题

最近得空把之前遇到的面试题做了一个整理,包括我本人自己去面试遇到的,还有其他人员去面试遇到的,还有网上刷到的,我都统一的整理了一下,希望对大家有用。

其中包含HTML、CSS、JavaScript、服务端与网络、Vue、浏览器等等

由于文章篇幅有限,仅展示部分内容

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值