(注:部分内容是来自所学视频里的内容)
举个小例子来说明封装的必要性、
(1)在没有面向对象封装前我们是这样写代码的
var divs = document.getElementsByTagName( 'div' );
for(var i = 0; i < divs.length; i++) {
divs[i].style.border = "1px dotted black";
}
然而,当你要获取其它的标签或是遍历获取到的标签,你就会重复上面的代码,当然也有几个单词不一样的啦,但是你不觉得你在做无用功吗?而且让你的代码看上去很冗余繁杂,你的工作伙伴也不愿意和你合作哒。So,有了面向对象的思想进行封装就好办了,下面请看这段代码….
var itcast = {
//获取元素模块
getEle: {
tag: function (tagName) {
return document.getElementsByTagName(tagName);
},
id: function (idName) {
return document.getElementById(idName);
}
},
//设置css模块
setCss: {
setStyle: function (arr) {
for(var i = 0; i < arr.length; i++) {
arr[i].style.border = "1px solid #abc";
}
},
css: function() {},
addClass: function() {},
removeClass: function() {}
// ...
}
};
var divs = itcast.getEle.tag(div);
itcast.setCss.setStyle(divs);
这样看起来是不是简单明了了很多,也不会有重复的代码。
JavaScript当中继承是指一个对象没有一些属性和方法,把另外有一个对象的属性和方法,拿过来自己用。
var obj = {};
var obj1= {
name : "继承",
sayHello: function() {
console.log("你好,我是继承");
}
}
for(var k in obj1){
//obj1[k]可以获取到对象的每一个属性
//这里使用k给对象新增属性的时候不可以使用点语法
obj[k]=obj1[k];
}
console.log(obj);
//(1)给原型对象添加新成员
function Person(name,age) {
this.name=name;
this.age=age;
}
Person.prototype.sayHello=function(){
alert(this.name+"你好");
}
var p=new Person("GJ", 18);
p.sayHello();
//(2)直接替换原型对象
function Person(name,age) {
this.name=name;
this.age=age;
}
var sister={
sayHello : function(){
alert(this.name+"你好");
}
}
Person.prototype=sister;
var p=new Person("GJ", 18);
p.sayHello();
//(3)利用混入的方式给原型对象添加成员
function Person(name,age) {
this.name=name;
this.age=age;
}
var sister={
sayHello : function(){
alert(this.name+"你好");
}
}
for(var i in sister){
Person.prototype[i]=sister[i];
}
var p=new Person("GJ", 18);
p.sayHello();
//注意:这种方式很可能把原型中的原有的对象给替换掉
function MyArray(){
//就可以在这里面添加你想添加的方法了(在下面继承了所有的Array属性和方法)
}
MyArray.prototype= [];
var NewArray=new MyArray();
NewArray.push(1);
NewArray.push(2,3,4);
alert(NewArray);
js中没有相应的体现,在强类型语言中比较常用。
简而言之,就是使用父类的变量接受子类的对象。
缺陷:只能创建一次对象,复用性较差,如果创建多个对象代码冗余度太高
var obj = {
name: "字面量",
type: "Object",
}
缺陷:想创建一个类似的对象,就会产生大量的代码
var box=new Object();
box.name='GJ';
box.age='18';
box.run=function() {
return this.name+this.age+'运行中。。。'
}
它解决了重复实例化问题,但还有个识别问题,因为根本无法搞清楚他们到底是哪个对象的实例
function createBox(name,age) {
var obj=new object();
obj.name= name;
obj.age=age;
box.run=function() {
return this.name+this.age+'运行中。。。'
}
return obj;
}
var obj = createBox('Gj',18);
既解决了重复实例化的问题,又解决了对象识别的问题
默认返回的是新创建的对象,如果我们自己写的return语句,return的是空值或是基本数据类型,返回的都是新创建的对象;如果返回的是object类型的值,将取而代之
function Box(name,age) {
this.name=name;
this.age=age;
this.run=function() {
return this.name+this.age+'运行中。。。'
}
}
var box1=new Box('GJ',100);
alert(box1.run());
- 原型是什么?
——-在构造函数创建出来的时候,系统会默认的帮构造函数创建并关联一个原型- 原型可以用来做什么?
——-原型中的属性和方法可以被使用该构造函数创建出来的对象使用- 如何访问构造函数的原型
——-构造函数.prototype- 如何给原型对象添加属性和方法
——–使用对象的动态特性
注意:当使用对象去访问属性和方法的时候,首先在对象自己内部查找,如果找到就直接使用,如果没有找到就用原型。
function Person(name,status) {
this.name=name;
this.status=status;
this.act=function(){
console.log("原型")
}
}
var p = new Person("xyz","single");
Person.prototype.move = function() {
console.log("我要做运动");
}
p.move();
每个构造函数都有原型对象
每个对象都会有构造函数
每个构造函数的原型都是一个对象
那么这个原型对象也会有构造函数
那么这个原型对象的构造函数也会有原型对象
这样就会形成一个链式的结构,称为原型链
function Person(name){
this.name=name;
}
var w=new Person();
//p ---> Person.prototype --->Object.prototype---->null
属性搜索的原则
——1.当访问一个对象的成员的时候,会先在自身找有没有,如果找到直接使用,
——2.如果没有找到,则去当前对象的原型对象中去查找,如果找到了直接使用,
——3.如果没有找到,继续找原型对象的原型对象,如果找到了,直接使用
——4.如果没有找到,则继续向上查找,直到Object.prototype,如果还是没有,就报错
成员 | 描述 |
---|---|
Object.prototype.proto | 指向当对象被实例化的时候,用作原型的对象。 |
Object.prototype.hasOwnProperty() | 返回一个布尔值 ,表示某个对象是否含有指定的属性,而且此属性非原型链继承的。 |
Object.prototype.isPrototypeOf() | 返回一个布尔值,表示指定的对象是否在本对象的原型链中。 |
Object.prototype.toString() | 返回对象的字符串表示。 |
Object.prototype.valueOf() | 返回指定对象的原始值。 |
———– Function函数所有的参数全都是字符串
———– Function函数的作用就是将所有的参数组合起来,变成一个函数
———– 1、如果只传一个参数,那么这个函数必然是函数体
———– 2、如果传多个参数,那么最后一个参数表示函数体,前面的参数代表将要创建的函数的参数
———– 3、如果不传参数,表示创建一个空函数
// 练习: 利用 Function 创建一个求三个数中最大数的函数.
var max = new Function("a", "b", "c", "return (a > b ? a : b)> c ? (a > b? a : b):c;");
1.可以使用字符串拼接 让代码换行
var max = new Function("arr",
"var maxNum = arr[0];" +
"for(var i = 1;i +
"if(maxNum < arr[i]){" +
"maxNum = arr[i];" +
"}" +
"}" +
"return maxNum;"
)
console.log(max([1, 2, 3, 44, 5, 6]));
2.使用模板的方式,将代码写在模板标签内,获取该标签的内容
window.onload =function () {
var script = document.getElementById("funcContent");
var str = script.innerHTML;
var max = new Function("arr", str);
console.log(max([1, 2, 3, 44, 5, 6]));
}
3.使用反引号(`) 引住字符串,那么就可以 换行了
ES6 语法(很少有浏览器实现) 使用键盘左上角的` 表示可换行字符串的界定符,之前我们用的是单引号或者双引号来表示一个字符串字面量,在ES6中可以用反引号来表示该字符串可换行。
//这是es6中的语法,存在兼容性问题
var str = `adfafdsa
asdfas`;
console.log(str);
首先来说下eval
eval函数可以用来将字符串转换成JavaScript代码并且运行
var str = “var a = 10”;
eval(str);
console.log(a);
使用eval来解析JSON格式字符串的时候,会将{}解析为代码块,而不是对象的字面量,解决办法是:
1.在JSON格式的字符串前面拼接上 “var o =”
2.把JSON格式的字符串使用()括起来,就不会将{}解析为代码块,而是表达式
var jsonData = '({"name":"zs", "age":18})';
var o = JSON.parse(jsonData);
console.log(o);
eval("var o = "+ jsonData);
var o = eval(jsonData);
console.log(o);
1.共同点:都可以将字符串转换成js代码
2.不同点:
1)function创建出来的是函数并不会直接调用,只有当手动去调用才可以执行
2)eval把字符串转成代码之后,直接就执行
函数内部的一个对象,在函数调用的时候,默认的会将所有传入的实参依次存入该对象(一个伪数组)
arguments.length:可以用来表示传入的实参的个数
静态成员:是指构造函数的属性和方法
实例成员:是指实例的属性和方法
function Person(){
this.name = "zs",
this.sayHello = function(){
console.log("Hello World");
}
}
//下面这个sayHi方法就是构造函数自己的方法,也就是静态方法
Person.sayHi = function(){
console.log("I'm a Person");
}
//原型属性属于构造函数,所以原型属性是静态属性
Person.prototype = {};
var p = new Person();
//这里的name是构造函数创建出来的实例对象的属性,所以是实例属性
p.name = "GJ";
//这里的sayHello也是构造函数创建出来的实例对象的方法,所以是实例方法
p.sayHello();
//在jQuery中,$("#id")是一个实例,所以它们都是实例成员
$("#id").css();
$("#id").text();
//像这种是jQuery内部的工具方法,属于静态方法
$.trim();
$.each();
$.extend();
//把工具方法,作为静态成员
//把跟对象相关的方法,作为实例成员
前端小白:所记内容有什么不对或是要完善的地方还望指出,感激不尽
小Tip:后期还会进行修改和补充