【JavaScript】手撕前端面试题:手写new操作符 | 手写Object.freeze

news2024/11/18 5:47:22

🖥️ NodeJS专栏:Node.js从入门到精通
🖥️ 博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)
🖥️ TypeScript知识总结:TypeScript从入门到精通(十万字超详细知识点总结)
🧑‍💼个人简介:大三学生,一个不甘平庸的平凡人🍬
👉 你的一键三连是我更新的最大动力❤️!
🏆分享博主自用牛客网🏆:一个非常全面的面试刷题求职网站,点击跳转🍬


文章目录

  • 前言
  • 1、手写new操作符
    • 要求
    • 手撕代码
  • 2、手写Object.freeze
    • 要求
    • 手撕代码
  • 结语

前言

向大家推荐一款博主一直在用的面试刷题求职网站:牛客网

牛客网不仅具有公司真题专项练习面试题库在线编程等功能,还具有非常强大的AI模拟面试功能,简直是求职者的福音!

牛客网里的题库非常全面的,无论你是前端还是后端,是想要备考还是准备面试又或者是想要提高自己,你都能在牛客网上找到适合自己的题,赶快点击链接去注册登录吧:点击进入牛客网

牛客网牛客网
在这里插入图片描述在这里插入图片描述

本篇文章所有示例参考自牛客网题库/在线编程/JS篇

1、手写new操作符

要求

补全JavaScript代码,要求实现new操作符的功能。


new 运算符介绍如下:

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

参数:

  • constructor
    一个指定对象实例的类型的类或函数。

  • arguments
    一个用于被 constructor 调用的参数列表。

new 关键字会进行如下的操作:

  1. 创建一个空的简单 JavaScript 对象(即 {});
  2. 为步骤 1 新创建的对象添加属性 __proto__,将该属性链接至构造函数的原型对象(设置它的原型为构造函数的原型对象);
  3. 将步骤 1 新创建的对象作为 this 的上下文;
  4. 如果该函数没有返回对象,则返回 this

手撕代码

const _new = function () {
    // 补全代码
    // 1. 创建一个空的简单 `JavaScript` 对象(即 `{}`);
    // 2. 为步骤 1 新创建的对象添加属性 `__proto__`,将该属性链接至构造函数的原型对象(设置它的原型为构造函数的原型对象);
    // 3. 将步骤 1 新创建的对象作为 `this` 的上下文;
    // 4. 如果该函数没有返回对象,则返回 `this`。
    const obj1 = {}; // 1
    const Fn = arguments[0]; // 获取函数参数
    Object.setPrototypeOf(obj1, Fn.prototype); // 2 
    const obj2 = Fn.apply(obj1, [].slice.call(arguments, 1)) // 3 
    return obj2 instanceof Object ? obj2 : obj1; // 4

}

[].slice.call(arguments, 1)的作用是获得一个arguments的拷贝数组,且该数组不含arguments的第一个元素。

我们知道数组的slice方法能够截取原数组的部分内容(返回一个新数组,不会修改原数组),但参数数组arguments是一个伪数组并不具有slice这个方法,所以这里使用call[].slicethis指定到arguments

测试一下:

function Fn(age) {
    this.name = 'Ailjx'
    this.age = age
}
console.log('new', new Fn(18));
console.log('_new', _new(Fn, 18));

在这里插入图片描述

2、手写Object.freeze

要求

补全JavaScript代码,要求实现Object.freeze函数的功能且该新函数命名为"_objectFreeze"


Object.freeze()函数介绍如下:

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改freeze() 返回和传入的参数相同的对象。

参数:

  • obj
    要被冻结的对象。

返回值:

  • 被冻结的对象。

手撕代码

需要注意的是:

  1. 注意不可枚举的属性也要重新冻结。
  2. 注意 Symbol 类型作为 key 值的情况,也要冻结。
  3. 注意只冻结对象自有的属性(使用 for ... in 会把原型链上的可枚举属性遍历出来)。
  4. 注意不可扩展性(不能添加新属性,使用 Object.preventExtensions()搭配configurable: falseObject.seal() 实现,同时也相当于把原型链冻结)。
const _objectFreeze = object => {
    // 补全代码
    if (typeof object !== 'object' || object === null) {
        throw new TypeError(`the ${object} is not a object`)
    }

    // Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组。
    const keys = Object.getOwnPropertyNames(object);

    // Object.getOwnPropertySymbols() 方法返回一个给定对象自身的所有 Symbol 属性的数组。
    const symbols = Object.getOwnPropertySymbols(object);
    
    [...keys, ...symbols].forEach(key => {
        // Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
        Object.defineProperty(object, key, {
            // 当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
            // configurable: false, // 如果下面使用的是Object.preventExtensions(object)而不是Object.seal(),则需要设置configurable: false
            
			// 当 writable 属性设置为 false 时,该属性被称为“不可写的”。它不能被重新赋值
            writable: false,
        })
    })

    // Object.seal()方法封闭一个对象,
    // 阻止添加新属性并将所有现有属性标记为不可配置。
    // 当前属性的值只要原来是可写的就可以改变。
    // 不会影响从原型链上继承的属性。但 __proto__ ( 已弃用 ) 属性的值也会不能修改。
    // Object.seal的效果相当于: 在Object.defineProperty时将configurable设置成false,同时对对象调用Object.preventExtensions。
    Object.seal(object)

    // Object.preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
    // 该方法使得目标对象的 [[prototype]] 不可变;任何重新赋值 [[prototype]] 操作都会抛出 TypeError 。这种行为只针对内部的 [[prototype]] 属性,目标对象的其它属性将保持可变。
    // Object.preventExtensions(object) 
    
    return object
}

知识点:

  • Object.getOwnPropertyNames() 方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性不包括 Symbol 值作为名称的属性)组成的数组。
  • Object.getOwnPropertySymbols() 方法返回一个给定对象自身的所有 Symbol 属性的数组。
  • Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
  • Object.seal() 方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。效果相当于: 在Object.defineProperty时将configurable设置成false,同时对对象调用Object.preventExtensions
  • Object.preventExtensions() 方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
    • Object.preventExtensions只防止添加属性,即不可扩展。
    • Object.seal除了不可扩展,也不可配置。
    • Object.freeze就像freeze的意思是被冻结,除了不可扩展,不可配置,也不可重写。

结语

这篇文章的所有内容都出自于牛客网的JS篇题库:
在这里插入图片描述

牛客网的JS题库非常贴合实际的,在写的过程查漏补缺能收获了很多,强烈将牛客网推荐给大家!

如果本篇文章对你有所帮助,还请客官一件四连!❤️

基础不牢,地动山摇! 快来和博主一起来牛客网刷题巩固基础知识吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/409622.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HttpServletRequest 获取参数

1 HttpServletRequest获取参数方法 可以使用HttpServletRequest获取客户端的请求参数,相关方法如下: String getParameter(String name):通过指定名称获取参数值;String[] getParameterValues(String name):通过指定名…

new bing 申请加入候补

最近Chatgpt非常的火爆, 微软也是把新版必应Chatgpt的测试版已经推出。1.下载安装新必应(new bing)需要下载 Edge新版本 Edge dev下载链接: Microsoft Edge 预览体验成员 (microsoftedgeinsider.com)安装插件在设置中找到扩展-> 获取Microsoft Edge扩展搜索获取 …

vue中的nexttick

我们了解nexttick之前,我们先来看一个例子。 我们先要每一次都在点击按钮的时候,都进行字符串的累加操作,并且在该函数中计算该字符串所占的高度offsetHeight,但是我们当进行第一次点击的时候,此时打印的结果不符合,因…

Javascript Object和Map之间的转换

简单的区分Map和Object Map是ES6退出的一个类型,特点:任何值都可作为属性名 Object特点:属性名只能是字符串(一开始我也不信,测试后才发现的) 代码图片创建一个map类型 new Map([[key, value],[key1, value1] ])简单的介绍下面…

vue 获取后端数据

目录 proxy 解决本地请求问题 vite Vue CLI fetch 代码演示 Post请求 ​编辑Get请求 Axios 安装 代码演示 Post请求 Get请求 TS 封装Axios 代码演示 proxy 解决本地请求问题 为什么会出现跨域问题? 浏览器的同源策略 首先给出浏览器“同源策略”的一种经典定义…

this.$router.push跳转页面携带参数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、params和query使用方式二、实现代码1.index.js代码2.test.vue代码3.testParams代码4.testParams代码5.效果总结前言 this.$router.push进行页面跳转时。携带…

Vue.js安装与创建默认项目(详细步骤)

前言 上一篇博文已经对Node.js的安装与配置进行了详细介绍,详见https://blog.csdn.net/qq_42006801/article/details/124830995 另外:文中项目存放的路径及项目名称可根据自身实际情况进行更改。 一、Vue.js简述 Vue是一套用于构建用户界面的渐进式Ja…

基于React的富文本编辑器——Braft Editor使用

antd 是基于 Ant Design 设计规范实现的 高质量 React 组件库,倾向于只提供符合该规范且带有视觉展现的 UI 组件,也尽量不重复造轮子。 如果要在React项目中使用富文本编辑器,官方推荐使用 react-quill 与 braft-editor。 详细点击这里 这篇…

Vue3.0项目——打造企业级音乐App(二)图片懒加载、v-loading指令的开发和优化

系列文章目录 内容参考链接Vue3.0 项目启动Vue3.0 项目启动(打造企业级音乐App)Vue3.0项目——打造企业级音乐App(一)Tab栏、轮播图、歌单列表、滚动组件Vue3.0项目——打造企业级音乐App(二)图片懒加载、…

「Vue面试题」vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?

文章目录一、是什么二、如何做接口权限路由权限控制菜单权限方案一方案二按钮权限方案一方案二小结参考文章一、是什么 权限是对特定资源的访问许可,所谓权限控制,也就是确保用户只能访问到被分配的资源 而前端权限归根结底是请求的发起权,…

Code For Better 谷歌开发者之声——谷歌Web工具包(GWT)

🍎个人主页:亮点菌的博客 🍊个人信条:点亮编程之路,做自己的亮点 文章目录一、GWT简介二、运行模式1、开发模式(以前称为托管模式)2、生产模式(以前称为Web模式)三、组件…

前端开发:JS的事件冒泡和事件捕获详解

前言 在前端开发过程中,关于JS原生的核心内容使用是日常工作中的常态,关于底层和原理的掌握使用,尤其是在性能优化方面甚为重要。作为前端开发的进阶内容,在实际开发过程中事件发生的顺序称为事件流,当触发某个事件的时…

微信小程序使用 npm 包,举例图文详解

使用 npm 包前提条件: 下载安装,配置npm环境变量,不懂得可以上网查教程,本文不再描述 小程序使用 npm 包简述 1、初始化 package.json 2、勾选允许使用 npm(新版微信小程序开发工具忽略这一步) 3、下载…

Auto.js的介绍

Auto.js 是一款无需root权限的javascript自动化软件 auto.js是一款安卓手机应用,和微信一样,安装在手机上使用 Auto.is是一款自动化软件,更根据脚本内容便可自动执行相关的操作,并且手机无需root Auto.js的脚本需要使用JavaScri…

Vue中的v-for循环,实现div块的循环生成

前言 大家好,这里是果力成,老规矩,学之!最近在做前端页面遇到一个小问题,说来也不难,但还是花费了我的好些时间,保持习惯记录一下。在前端学习中不免遇到一个div或者一个数组的循环产生,因为挨个儿传数据显然不是最优的。这里讲述…

强大的图片预览组件Viewer.js

​ 1、 Viewer.js简介 Viewer.js 是一款强大的图片查看器。我们通过Viewer.js 在页面上添加强大的图片查看功能,同时,这款优秀的插件配置操作起来也非常的方便。 Viewer.js分为2个版本,js版本和jquery版本,下载地址分别为 纯J…

uniapp组件uni-file-picker中对上传的图片进行压缩至1兆以内

我在做uniapp项目时,用的uni-file-picker组件,这是我做的一个项目实例,主要是将图片通过接口传至后台服务器 如果只是上传一张照片的话 还没有什么大问题,但是如果一连上传很多个图片,像我这个项目一样,而且…

一文搞懂ES6的Map

什么是Map Map是ECMAScript 6 的新增特性,是一种新的集合类型,为javascript带来了真正的键/值存储机 制。 Map 对象存有键值对,其中的键可以是任何数据类型。 Map 对象记得键的原始插入顺序。 Map 对象具有表示映射大小的属性。 Map的基…

海康视频WEB插件 V1.5.2 开发总结

文章目录前言一、效果图二、插件使用步骤总结三、具体步骤分析1.new 一个WebControl 插件实例2.启动插件服务3.创建视频播放窗口、绑定消息回调4.初始化参数,其中secret参数需要通过RSA加密,加密公钥通过WebControl.JS_RequestInterface获取5.通过WebCon…

前端使用html2canvas生成图片踩坑

前端使用html2canvas生成图片经验总结 前言 主要是总结一下html2canvas生成图片的基础用法,以及自己在使用html2canvas过程中踩过的坑和相应的解决思路 背景 近段时间接手一个项目,需要向设备下发某一个图片,为了该图片可以实时更改&…