js和cocos creator学习笔记

1.Javascript有哪些数据类型?举例两个最常见的内置对象数据类型?

常用的数据类型:Number,String,Boolean,Null,Undefined,Object
常见内置对象:Array,Function

2.下面代码输出内容是什么?

let a = [];
a[10] = 10;
console.log(a.length);
console.log(a[0]);
a[200] = undefined;
console.log(a.length);
console.log(a['10']);

    输出如下:

console.log(a.length);   //11
console.log(a[0]); //undefined
a[200] = undefined;
console.log(a.length); //201
console.log(a['10']); //10

3.下面代码输出内容是什么?

console.log(null==undefined);
console.log("1"==1);
console.log(0.3 == 0.1+0.2);
let obj1 = {
    
    a:1}; let obj2 = {
    
    a:1};
console.log(obj1==obj2);
let obj3 = obj1; obj3.a=100;
console.log(obj1==obj3);

    输出如下:

console.log(null==undefined);   //true
console.log("1"==1);            //true
console.log(0.3 == 0.1+0.2);    //false //这是因为浮点数在计算机中以二进制表示,而一些语言对十进制小数无法精确地表示为有限的二进制小数。0.1 和 0.2 都是十进制小数,但在计算机中以二进制表示时会有一些近似值,但不是完全相等的。 //0.3==0.3 是对的
console.log(obj1==obj2);      //false   引用地址不等
console.log(obj1==obj3);      //true    引用地址相等

4.document.addEventListener 和document.removeEventListener 在什么情况下会清除无效?

答题:

//错误实例
document.addEventListener('click', boundHandleClick.bind(this));   //错误

// 在某个时刻尝试移除事件监听器
document.removeEventListener('click', boundHandleClick.bind(this));   //错误
/*
*当我们尝试使用 removeEventListener 移除事件监听器时,由于绑定后的函数与原始函数不同,它们无
法匹配,因此无法正确移除监听器。因此,绑定 this 后的函数无法通过绑定后的函数来移除事件监听器。
*/

//正确案例
function handleClick(event) {
    
    
    console.log('点击事件处理程序', this);
}

const boundHandleClick = handleClick.bind({
    
     name: 'Example' });

document.addEventListener('click', boundHandleClick);

// 在某个时刻尝试移除事件监听器
document.removeEventListener('click', boundHandleClick);

5.js ,给了数字类型数组Array<number> ,返回最大值或最小值的几种方式

1种、使用 Math.max() 和 Math.min() 函数:
let arr = [1, 2, 3, 4, 5];  
let max = Math.max(...arr);  
let min = Math.min(...arr);2种、使用 reduce() 函数:
let arr = [1, 2, 3, 4, 5];  
let max = arr.reduce((max, val) => Math.max(max, val), -Infinity);  
let min = arr.reduce((min, val) => Math.min(min, val), Infinity);3种、使用 for 循环:
let arr = [1, 2, 3, 4, 5];  
let max = -Infinity;  
let min = Infinity;  
for(let i = 0; i < arr.length; i++) {
    
      
    if(arr[i] > max) {
    
      
        max = arr[i];  
    }  
    if(arr[i] < min) {
    
      
        min = arr[i];  
    }  
}

6.js 字符串去除重复字符。
    (1)、使用 Set 数据结构:

const str = "Hello World";
const uniqueStr = [...new Set(str)].join("");
console.log(uniqueStr); // Output: "Helo Wrd"

    这种方法利用了 Set 数据结构的特性,它只会存储唯一的值。将字符串转换为 Set 对象后,再将其转换回字符串即可得到去除重复字符的结果。

    (2)、使用正则表达式和 replace 方法:

const str = "Hello World";
const uniqueStr = str.replace(/(.)(?=.*\1)/g, "");
console.log(uniqueStr); // Output: "Helo Wrd"

    这种方法使用正则表达式和正向前瞻来匹配并删除重复字符。正则表达式 /(.)(?=.*\1)/g 匹配任意字符,并在该字符后面存在相同字符的情况下进行匹配。

  • .:匹配任意字符。
  • (?=.*\1):正向前瞻,确保当前位置后面存在相同的字符。
  • g:全局匹配,删除所有匹配的字符。

7.js 字符串去除某个字符

    (1)、使用正则表达式和 replace 方法:

const str = "Hello, World!";
const charToRemove = ",";
const removedStr = str.replace(new RegExp(charToRemove, "g"), "");
console.log(removedStr); // Output: "Hello World!"

    这种方法使用正则表达式来匹配并替换要删除的字符。通过将要删除的字符作为参数传递给 RegExp 构造函数,并指定 "g" 标志进行全局匹配,可以删除字符串中的所有匹配字符

    (2)、使用 split 和 join 方法:

const str = "Hello, World!";
const charToRemove = ",";
const removedStr = str.split(charToRemove).join("");
console.log(removedStr); // Output: "Hello World!"

    这种方法利用了字符串的 splitjoin 方法。首先,使用 split 方法将字符串按照要删除的字符拆分成数组,然后使用 join 方法将数组元素合并为一个新的字符串,从而达到删除指定字符的目的。

8.js 数组去除重复值
    (1)、使用 Set 数据结构:

const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // Output: [1, 2, 3, 4, 5]

这种方法利用了 Set 数据结构的特性,它只会存储唯一的值。将数组转换为 Set 对象后,再将其转换回数组即可得到去除重复值的结果。

    (2)、使用 filter 方法和 indexOf:

const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = array.filter((value, index, self) => {
    
    
  return self.indexOf(value) === index;
});
console.log(uniqueArray); // Output: [1, 2, 3, 4, 5]

    (3)、这种方法使用 filter 方法结合 indexOf 方法来筛选出数组中的唯一值。在回调函数中,通过判断当前元素的索引是否等于第一次出现的索引,从而确定是否为唯一值。

//使用 reduce 方法:
const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = array.reduce((accumulator, currentValue) => {
    
    
  if (!accumulator.includes(currentValue)) {
    
    
    accumulator.push(currentValue);
  }
  return accumulator;
}, []);
console.log(uniqueArray); // Output: [1, 2, 3, 4, 5]

    这种方法使用 reduce 方法遍历数组,并根据是否已经包含当前值来判断是否添加到结果数组中。

9.js 数组去除某一个值

    (1)、使用 filter 方法:

const array = [1, 2, 3, 4, 2, 5];
const valueToRemove = 2;
const filteredArray = array.filter((value) => value !== valueToRemove);
console.log(filteredArray); // Output: [1, 3, 4, 5]

    这种方法使用 filter 方法来筛选出不等于要删除的特定值的数组元素,从而得到一个新的数组。

    (2)、使用 splice 方法:

const array = [1, 2, 3, 4, 2, 5];
const valueToRemove = 2;
for (let i = array.length - 1; i >= 0; i--) {
    
    
  if (array[i] === valueToRemove) {
    
    
    array.splice(i, 1);
  }
}
console.log(array); // Output: [1, 3, 4, 5]

    这种方法使用 splice 方法来直接删除数组中与特定值相等的元素。需要注意的是,从后往前遍历并删除元素可以避免索引错位的问题。

(3)、使用 reduce 方法:

const array = [1, 2, 3, 4, 2, 5];
const valueToRemove = 2;
const filteredArray = array.reduce((accumulator, currentValue) => {
    
    
  if (currentValue !== valueToRemove) {
    
    
    accumulator.push(currentValue);
  }
  return accumulator;
}, []);
console.log(filteredArray); // Output: [1, 3, 4, 5]

    这种方法使用 reduce 方法遍历数组,并根据当前元素是否等于要删除的特定值来决定是否添加到结果数组中。

10.this的指向问题?
    如:哔哩哔哩视频解释
    百度一波有很多的

11.闭包的理解和使用场景
    如:哔哩哔哩视频解析

12.js 数组扁平化

function flattenArray(arr) {
    
    
  let result = [];
  arr.forEach(item => {
    
    
    if (Array.isArray(item)) {
    
    
      result = result.concat(flattenArray(item));
    } else {
    
    
      result.push(item);
    }
  });
  return result;
}

// 示例输入
const nestedArray = [1, [2, [3, 4], 5], 6, [7, 8]];

// 调用扁平化函数
const flattenedArray = flattenArray(nestedArray);

// 输出结果
console.log(flattenedArray);  //[1, 2, 3, 4, 5, 6, 7, 8]

13.一个构造函数在new的过程主要发生几件事情?

(可以百度网上有详细说明)
1.创建一个空对象
2.将函数的显示原型赋值给空对象的隐式原型
3.将函数的this指向空对象
4.返回新对象
注意当构造函数返回不是对象时,返回的还是this

14.js apply和bind和call的相同点和不同点?

    apply、bind和call是用于改变函数执行上下文的方法,它们有一些相同点和不同点,以及不同的实现原理。

    相同点:

    改变函数的执行上下文:apply、bind和call都用于改变函数内部的this指向,即指定函数执行时的上下文对象。
不同点:

    参数传递方式:apply和call都可以传递参数给函数,但方式不同。apply接受一个包含参数的数组或类数组对象,而call接受逐个列举的参数。bind可以进行部分参数的绑定,返回一个新函数,新函数可以稍后调用并传递剩余的参数。

    返回值:apply和call方法在调用时会立即执行函数,并返回函数的结果。bind方法返回一个新的函数,不会立即执行原函数。


cocos creator提问
1、屏幕适配的原理是什么?
    (1).设计分辨率,对于考美术设计时需要一个分辨率大小来为开发设计提供一个参考并适配到不同手机分辨率上。
    (2).适配策略:适配高度/适配宽度
比如在游戏横屏中,我们适配高度,就需要将设计稿中的设计高度和视口高度做个比例换算,这样在游戏屏幕中,展示的效果就是按比例换算出来的展示效果。
对于不同型号的手机,手机高度和宽度都不一样,不一定符合设计稿高宽比例,如何实现排版和位置效果?
    ①停靠点:游戏中可以通过Widget组件脚本对其上下左右中这些点做一个靠边或居中等操作;
    ②边界区域大小宽度调整;
    ③内容缩放或者通过Layout布局;

2、cocos creator 的生命周期和使用?
    (1)生命周期概述:

    onLoad:在节点被加载后立即调用,用于初始化节点和组件的一些设置。
    start:在 onLoad 执行完毕后调用,用于进行需要等待所有节点和组件初始化完成后才能执行的操作。
    update:每一帧都会被调用,用于更新游戏逻辑和状态。
    lateUpdate:在 update 后被调用,用于进行一些需要在 update 之后执行的操作。
    onDestroy:在节点被销毁前调用,用于进行一些清理工作。
生命周期的使用方法:

    在 Cocos Creator 中,你可以通过在脚本组件中定义这些生命周期函数来使用它们。
    在脚本组件中编写对应的函数,例如 onLoad()、start()、update() 等,并在函数内部实现相应的逻辑。
    这些函数会自动在对应的时机被调用,你可以在函数内部进行初始化设置、资源加载、游戏逻辑的更新等操作。
    如果你需要在某个节点上挂载脚本组件并使用其生命周期函数,可以通过编辑器界面选择节点并添加相应的组件。

生命周期的注意事项:

    生命周期函数的执行顺序是固定的,你可以依赖这些顺序来正确管理游戏对象和状态。
避免在生命周期函数中进行耗时的操作,以免影响游戏性能。
在 onDestroy 生命周期函数中进行资源释放和清理工作,以避免内存泄漏和资源浪费。

3、cocos creator 的生命周期的onLoad和start的区别以及作用?
    (1)、onLoad 生命周期函数:

    作用:在节点被加载后立即调用,用于初始化节点和组件的一些设置。它是一个初始化阶段的入口点。

    调用时机:当节点和它的组件被实例化并添加到场景中后,onLoad 函数会被调用。在 onLoad 函数执行前,节点和组件的属性已经被赋值,但此时并不保证其它相关节点和组件的 onLoad 函数已经执行完毕。

    使用场景:在 onLoad 中可以进行初始化设置、获取引用、注册事件监听器等操作。也可以在该函数中进行资源加载、网络请求等异步操作,但需要注意异步操作的执行时间和顺序。
    (2)、start 生命周期函数:

    作用:在 onLoad 执行完毕后,会调用 start 函数。它是节点和组件完成初始化后的入口点。

    调用时机:当节点和它的组件初始化完成后,start 函数会被调用。在 start 函数执行前,所有节点和组件的 onLoad 函数已经执行完毕。

    使用场景:在 start 中可以进行一些需要等待所有节点和组件初始化完成后才能执行的操作,例如动画的播放、定时器的启动、游戏逻辑的初始化等。

4、cocos creator 的生命周期ondisable和ondestroy的的作用和使用?
它们用于管理游戏对象的禁用和销毁过程。

    (1)、onDisable 生命周期函数:

    作用:在节点被禁用时调用,用于进行一些在节点禁用时需要执行的操作。
调用时机:当节点被禁用时(例如将节点从场景中移除或禁用节点的父节点),onDisable 函数会被调用。
    使用场景:在 onDisable 中可以暂停一些与节点相关的逻辑、停止计时器、取消事件监听器等操作。
    注意事项:onDisable 函数不会在节点首次被创建时被调用,只有在节点之前处于激活状态并被禁用时才会触发。
    (2)、onDestroy 生命周期函数:

    作用:在节点被销毁前调用,用于进行一些清理工作和资源释放操作。
    调用时机:当节点被销毁时(例如从场景中移除节点或直接调用节点的 destroy 方法),onDestroy 函数会被调用。
    使用场景:在 onDestroy 中可以释放节点和组件的资源、取消事件监听器、清理定时器等操作。
    注意事项:onDestroy 函数是在节点即将被销毁时调用,此时节点和组件的属性和方法仍然可用,但其它相关的节点和组件可能已经被销毁。
需要注意的是,禁用节点并不会立即触发 onDestroy 函数。如果你需要在节点被销毁前执行一些操作,可以在 onDisable 中进行相关的处理,或者在外部调用节点的 destroy 方法来主动触发 onDestroy 函数。

5、cocos creator 热更新原理?
Cocos Creator 的热更新功能允许游戏在运行时进行代码和资源的更新,而无需重新发布整个游戏。下面是 Cocos Creator 热更新的基本原理:

    服务器端资源存储:

    在热更新过程中,需要一个服务器端存储游戏的更新资源文件,通常使用 HTTP 或者其他网络协议进行资源的下载和更新。
    版本管理:

    在游戏中,需要定义版本号来标识当前游戏的版本。可以使用一个配置文件或者服务器 API 返回的数据来获取最新的游戏版本号。
    资源更新检查:

    游戏在启动时会向服务器发送请求,检查是否有新的版本可供更新。通常会比较本地游戏的版本号和服务器上的最新版本号。
    下载更新资源:

    如果有新的版本可供更新,游戏会根据服务器提供的资源清单文件(通常是一个 JSON 文件)获取需要更新的资源列表。
    游戏会根据资源列表逐个下载资源文件到本地存储设备,可使用 Cocos Creator 提供的下载器或自定义下载逻辑。
    更新资源文件:

    下载完成后,游戏会将新的资源文件替换掉本地旧的资源文件。这样游戏在使用资源时将加载最新的文件。
    代码更新检查和替换:

    对于 JavaScript 代码的更新,可以使用 eval 函数或动态创建

6、xml和json的区别?
    XML(可扩展标记语言)和 JSON(JavaScript 对象表示法)是两种常用的数据交换格式,它们有以下区别:

语法结构:

    XML 使用标签和属性的层次结构表示数据,例如 content。
JSON 使用键值对的结构表示数据,例如 { “key”: “value” }。
数据类型支持:

    XML 不直接支持数据类型,所有的数据都以字符串的形式表示。需要根据应用程序的需求进行解析和转换。
    JSON 支持多种数据类型,包括字符串、数字、布尔值、数组和对象等。
可读性:

    XML 具有自我描述性,标签和属性的命名可以更具可读性和可理解性。
    JSON 的语法更加简洁,对于复杂的数据结构可能更易于阅读和编写。
文件大小:

    XML 文件通常比 JSON 文件更大,因为 XML 使用了更多的标签和属性。
    JSON 文件相对较小,因为它使用简洁的键值对结构。
解析和序列化:

    XML 的解析和序列化需要使用额外的库或自定义解析器。
    JSON 的解析和序列化是 JavaScript 的原生支持,可以直接使用     JSON.parse() 和 JSON.stringify() 进行操作。
数据交互:

    XML 在传输和交互中更常用于 SOAP、RSS、配置文件等领域。
    JSON 在 Web 应用程序中更常用,特别是与 JavaScript 语言的交互和数据传输。
选择使用 XML 还是 JSON 取决于具体的需求和场景。XML 更适合于具有复杂结构和自描述性要求的数据,而 JSON 更适合于轻量级的数据交换和与 JavaScript 的交互。此外,还应考虑与其他系统、工具和语言的兼容性以及数据传输的效率等因素。

7、对象池是消耗CPU还是GPU?
    对象池(Object Pool)是一种设计模式,用于管理可重复使用的对象实例,以提高性能和资源利用率。对象池的实现通常是在内存中维护一组预先创建的对象,并在需要时从池中获取对象,而不是频繁创建和销毁对象。

    对象池本身并不直接涉及到 CPU(中央处理器)或 GPU(图形处理器)的消耗。它是一种软件设计模式,主要关注的是资源的重复使用和管理。

    然而,在特定的上下文环境中,对象池的使用可能会对 CPU 或 GPU 的消耗产生一定的影响。例如,在游戏开发中,对象池的使用可以减少对象的频繁创建和销毁,从而降低 CPU 的开销。这是因为对象的创建和销毁涉及到内存分配和释放等操作,而对象池可以避免这些开销,提高性能。

    另一方面,对象池的使用也可以对 GPU 产生一定的影响,特别是在涉及到图形渲染的场景中。对象池可以管理可重复使用的渲染资源(例如纹理、模型等),从而减少资源加载和释放的开销,提高 GPU 的效率。

    总的来说,对象池本身是一种软件设计模式,不直接涉及 CPU 或 GPU 的消耗。然而,通过优化资源的重复使用和管理,对象池可以在特定的上下文环境中对 CPU 和 GPU 的消耗产生积极的影响,提高性能和资源利用率。

猜你喜欢

转载自blog.csdn.net/mingketao/article/details/132260110