"宿主对象"和"原生对象"这两个概念主要涉及到 JavaScript 运行环境中的对象。
原生对象(Native Objects):
宿主对象(Host Objects):
window
、document
、XMLHttpRequest
等。在 Node.js 环境中,宿主对象包括 global
、process
、Buffer
等。Attribute
是在HTML中定义的,而property
是在DOM上定义的。
为了说明区别,假设我们在HTML中有一个文本框:
const input = document.querySelector('input');
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello
但是在文本框中键入“ World!”后:
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello World!
'use strict'
是用于对整个脚本或单个函数启用严格模式的语句。严格模式是可选择的一个限制 JavaScript 的变体一种方式 。
优点:
缺点:
call
、apply
和 bind
是 JavaScript 中用于改变函数执行上下文的方法。它们的作用都是为了在调用函数时明确指定函数内部的 this
值,并且可以传递参数。
call
方法:
call
方法用于调用函数,并将一个指定的 this
值和若干个参数传递给函数。function.call(thisArg, arg1, arg2, ...)
apply
方法:
apply
方法也用于调用函数,但是它接受一个包含参数的数组作为函数执行时的参数。function.apply(thisArg, [arg1, arg2, ...])
bind
方法:
bind
方法用于创建一个新函数,新函数的 this
值由 bind
的第一个参数指定,其余参数作为新函数的参数。bind
方法不会立即执行函数,而是返回一个绑定了指定 this
值的新函数。function.bind(thisArg[, arg1[, arg2[, ...]]])
区别:
call
和 apply
的区别: 主要在于参数的传递方式,call
是一个一个传递,而 apply
是通过数组传递。bind
的区别: bind
方法创建了一个新函数,并预先设置了函数的 this
值和一部分参数,但不会立即执行。它返回一个新函数,需要调用该新函数才会执行原函数。示例:
// 示例函数
function greeting(message) {
console.log(message, this.name);
}
var person = {
name: 'John'
};
// 使用 call
greeting.call(person, 'Hello'); // 输出: Hello John
// 使用 apply
greeting.apply(person, ['Hi']); // 输出: Hi John
// 使用 bind
var boundGreeting = greeting.bind(person, 'Hola');
boundGreeting(); // 输出: Hola John
var arr = [];
if (Array.isArray(arr) && arr.length === 0) {
console.log('是空数组');
}
// Array.isArray是ES5提供的,如果不支持。用下面的方案。
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
map
: 遍历数组,返回回调返回值组成的新数组forEach
: 无法break,可以用try/catch中throw new Error来停止filter
: 过滤some
: 有一项返回true,则整体为trueevery
: 有一项返回false,则整体为falsejoin
: 通过指定连接符生成字符串sort(fn) / reverse
: 排序与反转,改变原数组concat
: 连接数组,不影响原数组, 浅拷贝slice(start, end)
: 返回截断后的新数组,不改变原数组splice(start, number, value...)
: 返回删除元素组成的数组,value 为插入项,改变原数组indexOf / lastIndexOf(value, fromIndex)
: 查找数组项,返回对应的下标reduce / reduceRight(fn(prev, cur), defaultPrev)
: 两两执行,prev
为上次化简函数的return值,cur
为当前值(从第二项开始)数组乱序:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.sort(function () {
return Math.random() - 0.5;
});
数组拆解:
// flat: [1,[2,3]] --> [1, 2, 3]
Array.prototype.flat = function() {
return this.toString().split(',').map(item => +item )
}
push、pop、shift、unshift功能及返回值
push:添加新元素到数组末尾,返回数组长度
pop:移除数组最后一个元素,返回元素本身
unshift:添加新元素到数组开头,返回数组长度
shift:移除数组首个元素,返回元素本身
以上4种操作均会改变数组本身
map用法:
let array = [1, 2, 3, 4, 5];
let newArray = array.map((item, i, arr) => {
return item * 2;
});
console.log("array:", array); // [1, 2, 3, 4, 5]
console.log("newArray:", newArray); // [2, 4, 6, 8, 10]
// 此处的array接受map方法运算之后的返回值
// 但是map方法并不能改变原来的数组
forEach用法:
let array = [1, 2, 3, 4, 5];
let newArray = array.forEach((item, i, arr) => {
console.log('item:' + item + ', index:' + i);
// array[i] = item * 2; // 可以用这种方式改变原始数组的值
});
console.log("array:", array); // [1, 2, 3, 4, 5]
console.log("newArray:", newArray); // undefined
// forEach方法没有返回值
能用forEach()做到的,map()同样可以。反过来也是如此。
map()会分配内存空间存储新数组并返回,forEach()不会返回数据。
forEach()允许callback更改原始数组的元素。map()返回新的数组。
使用展开运算符(Spread Operator):
function getArgumentsArray() {
var argsArray = [...arguments];
return argsArray;
}
var result = getArgumentsArray(1, 2, 3);
console.log(result); // 输出: [1, 2, 3]
使用 Array.prototype.slice 方法:
function getArgumentsArray() {
var argsArray = Array.prototype.slice.call(arguments);
return argsArray;
}
var result = getArgumentsArray(1, 2, 3);
console.log(result); // 输出: [1, 2, 3]
for循环
for (let property in obj) {
console.log(property);
}
但是,这还会遍历到它的继承属性,在使用之前,你需要加入obj.hasOwnProperty(property)检查。
Object.keys()
Object.keys(obj).forEach((property) => { ... })
Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组。
Object.getOwnPropertyNames()
Object.getOwnPropertyNames(obj).forEach((property) => { ... })
Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组。
for loops
for (let i = 0; i < arr.length; i++) { ... }
forEach
arr.forEach((item, index, arr) { ... })
map
arr.map((item, index, arr) => { ... })
1)typeof: 适合基本的数据类型和函数
console.log(typeof bool); // boolean
console.log(typeof num); // number
console.log(typeof str); // string
console.log(typeof und); // undefined
console.log(typeof nul); // object
console.log(typeof arr); // object
console.log(typeof obj); // object
console.log(typeof fun); // function
2)instanceof: 判断对象类型,基于原型链去判断。
obj instanceof Object: 左操作数是一个对象,右操作数是一个函数构造器或者函数对象,判断左边的操作数的原型链_proto_属性是否有右边这个函数对象的proptotype属性。
console.log(bool instanceof Boolean);// false
console.log(num instanceof Number); // false
console.log(str instanceof String); // false
console.log(und instanceof Object); // false
console.log(arr instanceof Array); // true
console.log(nul instanceof Object); // false
console.log(obj instanceof Object); // true
console.log(fun instanceof Function);// true
var bool2 = new Boolean()
console.log(bool2 instanceof Boolean);// true
var num2 = new Number()
console.log(num2 instanceof Number);// true
var str2 = new String()
console.log(str2 instanceof String);// true
function Animation(){}
var ani = new Animation()
console.log(ani instanceof Animation);// true
function Dog(){}
Dog.prototype = new Animation()
var dog = new Dog()
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animation);// true
console.log(dog instanceof Object); // true
从结果中看出instanceof不能区别 undefined 和 null,而且对于基本类型如果不是用new声明的则也测试不出来,对于是使用new声明的类型,它还可以检测出多层继承关系。
3)constructor: 返回对创建此对象的函数的引用
console.log(bool.constructor === Boolean); // true
console.log(num.constructor === Number); // true
console.log(str.constructor === String); // true
console.log(arr.constructor === Array); // true
console.log(obj.constructor === Object); // true
console.log(fun.constructor === Function); // true
console.log(ani.constructor === Animation); // true
console.log(dog.constructor === Dog); // false
console.log(dog.constructor === Animation);// true
null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。
函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失。所以dog.constructor === Animation 而不是 Dog
4)Object.prototype.toString.call
console.log(Object.prototype.toString.call(bool)); //[object Boolean]
console.log(Object.prototype.toString.call(num)); //[object Number]
console.log(Object.prototype.toString.call(str)); //[object String]
console.log(Object.prototype.toString.call(und)); //[object Undefined]
console.log(Object.prototype.toString.call(nul)); //[object Null]
console.log(Object.prototype.toString.call(arr)); //[object Array]
console.log(Object.prototype.toString.call(obj)); //[object Object]
console.log(Object.prototype.toString.call(fun)); //[object Function]
console.log(Object.prototype.toString.call(dog)); //[object Object]
原文见下面链接
「2023」前端面试知识点复盘——JS篇 - 掘金